How to package C++ plugin without private source code (only binaries + headers) in 4.20?

I’m trying to package my own C++ plugin using Unreal Engine 4.20 and afterwards strip out some of the source code, while still leaving binaries so the plugin can be used with editor and game distributions. (This is a requirement for my company for IP protection, so please don’t respond if you’d like to suggest not doing this - it’s out of my control and I love FOSS as much as the next guy. Business gonna business.)

It seems this process may have changed in the last few engine versions. I’ve got plugin examples here from earlier engine versions of this setup working so I know it’s possible. In these examples, the plugin’s Source*\Private folders were deleted, but as long as the plugin still contains the Source*.Build.cs files and Source*\Public files, and also contains Binaries\Win64*.dll/lib for all build configurations + platforms, I can rebuild a C++ project hosting the plugin in Visual Studio or via UE4’s automatic rebuild process when opening the .uproject file, and I get no warnings or errors.

There’s some prior discussion of getting this working here, though I haven’t found a single clear tutorial or step-by-step guide on how to do it:

https://forums.unrealengine.com/deve…lugin-possible
https://forums.unrealengine.com/deve…-distribution=

In 4.20 this process doesn’t seem to work, though I’m not 100% sure of the correct steps, and there’s no real documentation I can find on it. I think all I’m supposed to do is remove the Source\Private folders. But if I package the plugin via the editor, strip out the private source files, then add it to a C++ project and build the “Development Editor” profile in Visual Studio I see:

1>UnrealBuildTool : error : UBT ERROR: Failed to produce item: <MYPROJECT>\Plugins&lt;MYPLUGIN>\Intermediate\Build\Win64\UE4Editor\Development&lt;MODULEINSIDETHEPLUGIN>\UE4Editor-<MODULEINSIDETHEPLUGIN>.suppressed.exp
1> (see …/Programs/UnrealBuildTool/Log.txt for full exception trace)

The UnrealBuildTool log file gives no further clues.

The other thing I’ve noticed that seems odd is that packaging my plugin does not generate .lib files under Binaries\Win64, only .dll files. I would have expected .lib files for the Development, Shipping builds etc. So I’m wondering if this is part of the problem.

I’ve read through Plugins in Unreal Engine | Unreal Engine 5.2 Documentation and had a dig through old forum threads/AnswerHub responses, but I couldn’t find a clear tutorial or example on how to do this.

Any pointers greatly appreciated!

1 Like

I’ve been doing some more digging today. It seems plugin binary layouts have definitely changed from 4.19 to 4.20. Specifically it looks like most plugin module static library files that used to live under Binaries&lt;platform>\xxx-.lib have now been replaced with .cpp.obj and .precompiled files under Intermediate\Build\Win64\UE4&lt;build>&lt;module>. As an example here’s the layout of the precompiled engine folder “Engine\Plugins\Runtime\WindowsMoviePlayer” in 4.19 vs 4.20:

4.20
Engine\Plugins\Runtime\WindowsMoviePlayer\Binaries\Win64\UE4Editor-WindowsMoviePlayer.dll
Engine\Plugins\Runtime\WindowsMoviePlayer\Binaries\Win64\UE4Editor-WindowsMoviePlayer.pdb
Engine\Plugins\Runtime\WindowsMoviePlayer\Binaries\Win64\UE4Editor.modules
Engine\Plugins\Runtime\WindowsMoviePlayer\Intermediate\Build\Win32\UE4\Development\WindowsMoviePlayer\Module.WindowsMoviePlayer.cpp.obj
Engine\Plugins\Runtime\WindowsMoviePlayer\Intermediate\Build\Win32\UE4\Development\WindowsMoviePlayer\WindowsMoviePlayer.precompiled
Engine\Plugins\Runtime\WindowsMoviePlayer\Intermediate\Build\Win32\UE4\Shipping\WindowsMoviePlayer\Module.WindowsMoviePlayer.cpp.obj
Engine\Plugins\Runtime\WindowsMoviePlayer\Intermediate\Build\Win32\UE4\Shipping\WindowsMoviePlayer\WindowsMoviePlayer.precompiled
Engine\Plugins\Runtime\WindowsMoviePlayer\Intermediate\Build\Win64\UE4\Development\WindowsMoviePlayer\Module.WindowsMoviePlayer.cpp.obj
Engine\Plugins\Runtime\WindowsMoviePlayer\Intermediate\Build\Win64\UE4\Development\WindowsMoviePlayer\WindowsMoviePlayer.precompiled
Engine\Plugins\Runtime\WindowsMoviePlayer\Intermediate\Build\Win64\UE4\Shipping\WindowsMoviePlayer\Module.WindowsMoviePlayer.cpp.obj
Engine\Plugins\Runtime\WindowsMoviePlayer\Intermediate\Build\Win64\UE4\Shipping\WindowsMoviePlayer\WindowsMoviePlayer.precompiled
Engine\Plugins\Runtime\WindowsMoviePlayer\Intermediate\Build\Win64\UE4Editor\Development\WindowsMoviePlayer\UE4Editor-WindowsMoviePlayer.lib

vs

4.19
Engine\Plugins\Runtime\WindowsMoviePlayer\Binaries\Win32\UE4-WindowsMoviePlayer-Win32-Shipping.lib
Engine\Plugins\Runtime\WindowsMoviePlayer\Binaries\Win32\UE4-WindowsMoviePlayer.lib
Engine\Plugins\Runtime\WindowsMoviePlayer\Binaries\Win64\UE4-WindowsMoviePlayer-Win64-Shipping.lib
Engine\Plugins\Runtime\WindowsMoviePlayer\Binaries\Win64\UE4-WindowsMoviePlayer.lib
Engine\Plugins\Runtime\WindowsMoviePlayer\Binaries\Win64\UE4Editor-WindowsMoviePlayer.dll
Engine\Plugins\Runtime\WindowsMoviePlayer\Binaries\Win64\UE4Editor.modules
Engine\Plugins\Runtime\WindowsMoviePlayer\Intermediate\Build\Win64\UE4Editor\Development\UE4Editor-WindowsMoviePlayer.lib

I also found a bunch of bugs/issues from the 4.20 Preview + Release threads relating to packaging plugins - some of these have been fixed already:

https://forums.unrealengine.com/unreal-engine/announcements-and-releases/1485599-unreal-engine-4-20-preview?p=1494486#post1494486
https://forums.unrealengine.com/unreal-engine/announcements-and-releases/1485599-unreal-engine-4-20-preview?p=1496041#post1496041
https://forums.unrealengine.com/unreal-engine/announcements-and-releases/1485599-unreal-engine-4-20-preview?p=1491732#post1491732
https://forums.unrealengine.com/unreal-engine/announcements-and-releases/1485599-unreal-engine-4-20-preview?p=1500039#post1500039

So to me this indicates Epic have done some work in the area of plugin packaging, and I’m not sure if anyone has tested stripping out the Private source code folders in 4.20. Is this no longer supported? I know several companies that were using this technique to distribute plugins with trade secrets in the source code.

More digging - updating progress here for the internet archaeologists of the future. I’ve updated to and tested 4.20.2 but the behaviour persists.

I have had a small breakthrough though. If I package the plugin via the editor, then in the packaged output files, remove the Source*\Private folders and in the .Build.cs files for modules used in the plugin, add “bUsePrecompiled = true;”, the C++ host project will at least build successfully with the stripped back plugin (as it seems to skip compilation for the plugin entirely). However, it fails to compile DebugGame or DebugGame Editor, and if I rebuild or clean the build configuration it will delete the plugin binaries/intermediate files, forcing the user to manually copy them back in place again.

So that’s some progress at least, but I’d really love the opinion of someone at Epic on this, as I think the bUsePrecompiled functionality is mostly used by the engine to distribute binary-only versions of modules through the launcher. It makes sense they wouldn’t include precompiled versions of DebugGame, since this functionality is only intended for engine-side code, not game-side code. I could be wrong though.

It’s probably been more than 10 engine versions since I experimented with doing this, so I don’t know if it became better supported than it was back then. I do know that during 4.20 preview there were issues building plugins just in the regular way, with errors relating to the new .precompiled files. From taking a quick look at the UBT code I think you’re on the right track with setting the bUsePrecompiled option. With that flag set, it looks like UBT skips compiling entirely and just copies in references to the object files from somewhere, which is presumably what you need. I don’t get the impression it’s intended for launcher engine modules only; if anything, it seems they may have generalized what they had before so that it can be applied in other cases, such as plugins.

Debug configs not working is to be expected I think, as the default plugin packaging process only compiles the plugin under Development and Shipping configs. If you need to distribute debug builds too, I think you’ll just need to run your own script instead (you could modify the existing BuildPlugincommand). Though of course that would depend on the new precompiled stuff not being hard coded with the assumption that it will never be used in a Debug config.

As for the clean issue, no idea. I’ve run into similar problems many times, and in the end I just try to avoid doing anything remotely non-standard with UE4 because you can guarantee these kind of headaches when you do. A far nicer approach than doing all of this would be to wrap up the protected code in a third party library, and then just have your module link that in and provide an integration layer. Obviously though that may be totally infeasible depending on how UE4-specific the code in question is.

We have been having the same problem, we want to be able to release a binary only plugin version of our middleware for people to try out. Our approach is almost the same as yours, so we have encountered the same problems with UE4.20.

What I discovered is that previously we had been telling users to install our binary only plugin as a Game plugin, however there was a UBT fix in 4.20, “UBT: Fix errors during incremental builds if a build contains an exported symbol change…”, that meant that our precompiled libs were now being deleted and we were getting similar errors as you.

Our workaround has been to change our instructions to tell users to install it as an Engine plugin instead. If you put the plugin in the engine folder then UBT no longer tries to rebuilt it and the problems go away.

I’ve written this blog post about the process we use: https://mercuna.com/building-binary-…real-engine-4/

hi,I`d like to do give plugin-developers a engine with no .cpp. for example,I build a engine and delete all the .cpp files in private folder,then i give these files and dlls to plugin-developers. they use this engine version to create their plugin ,build and test(no .cpp). My idea is to skip build all the modules which have no .cpp,I am not sure if it is possible.can anyone give me some advice?thanks

Any solution yet?

Create and compile your own static library binary in Visual Studio; then ship plugin with .h + lib file, no .cpp needed.

But after you try to compile the project it will stop working ( even when it compiled successfully ).

To add to this, according to my test, from 4.20.x onward you can deploy and use a Plugin without any source files in it (no header and no cpp) as long as:

  • It has been packaged from the Plugin window (click Package under the plugin)
  • There is an Intermediate folder from the packaging, which contains all precompiled objects and other auto generated files
  • It still contains the plugin Build.cs file inside (but all Private/Public folders can be removed)
  • The build file contains the statement: bUsePrecompiled = true;
  • There is Binaries folder with the plugin dll
  • There is a Resource folder with the plugin icon
  • There is a Content folder if the plugin contains any content

Such plugin will work in the Editor and will package together with the game. This works with BP only projects of course. For plugin exposing C++ functions you still need at least the headers in the Public folder.

Cheers,
Marco.

8 Likes

A ■■■■■■■ hero