We are attempting to conditionally compile files (including UObjects) within a Plugin based on the target configuration (dev/shipping etc). Our setup is that we have a base “Debugging” plugin (essentially, an ImGui implementation) which contains a single “DeveloperTools” module, and our project has numerous other plugins/modules within which we want to compile optional files when this base plugin is also compiled for the target configuration.
The standard way to approach this it seems, would be to create “DeveloperTools” modules within those plugins. We haven’t yet attempted this, but the key issue is that this would require the “Runtime” part of the plugin to export symbols purely for the purpose of the debugging tool, which we want to avoid. There is no ability to conditionally export classes/symbols for different build configurations because of UHT.
So instead, we are making use of ConditionalAddModuleDirectory() to append folders when appropriate. The setup of one of our “debuggable” plugins is as follows:
// .UPlugin file - only declares a single “Runtime” module which is always compiled.
MyPlugin.uplugin { "Modules": [ { "Name": "MyPluginRuntime", "Type": "Runtime", "LoadingPhase": "Default" } }
// MyPluginRuntime.Build.cs - Conditionally adds the additional paths if the “DebugPlugin” is built.
public MyPluginRuntime(ReadOnlyTargetRules Target) : base(Target) { if (IsPluginEnabled("DebugPlugin")) { string DebugModulePath = Path.Combine(ModuleDirectory, "..", Name + "Debug"); ConditionalAddModuleDirectory(new DirectoryReference(DebugModulePath)); } }
// MyPluginDebug.Builds.cs - Adds additional folder paths.
public MyPluginDebug(ReadOnlyTargetRules Target) : base(Target) { PrivateIncludePaths.AddRange(new string[] { "MyPluginDebug/Private" }); }
We can see that this is working - logging the folders/files that UBT acquires from UEBuildModuleCPP.cs.Compile, we can see the “Debug” folders are excluded when building shipping, and included for other builds (which is correct for our setup)
Unfortunately, our issue is that when we start a build on our build farm via Horde, the build fails to build non-shipping builds due to missing ###.gen.cpp files and/or missing ###.generated.h files (our debug modules contain UObjects/reflected types). However, this is only the case when we start a task that builds Development/Test binaries as well as Shipping binaries. (Note that we are deliberately including developer/debug tools for test configurations)
If we send the different build configurations to the farm separately (i.e, build shipping first, then build development/debug), the build succeeds. The issue almost seems to be that the machines are sharing compilation units for different build configurations when performing a batched build. Since UHT has (rightfully) not produced generated code for the shipping build, the development/debug builds fail. Presumably, this is a non-deterministic failure based on whichever configuration is built first.
We have also seen issues with incremental builds failing. We tried using pre-processor to essentially comment-out the types but since they are UCLASS, that’s not possible. Is there a canonical way to achieve this that doesn’t involve creating a second, fully-fledged debugging module and exporting otherwise internal types/symbols from our runtime module?