Are ALL modules in a project supposed to be added to packaged builds?

Hey everyone!
I’ve always heard that “only modules in the dependency chain get shipped into builds”. After some testing though, that doesn’t seem to be entirely true.

In order to test that theory, I created a blank C++ game project, and added an empty module with a simple UE_LOG in its StartupModule function. No other modules depend on this module, and it was not in the ExtraModuleNames of the .target.cs file. I did add it to the .uproject file, to set up its loading phase. After packaging a development build and running it, the log was there (which meant the module was packaged with the build). It seems that a module will be shipped into a build just by being added to the .uproject, regardless of being in the dependency chain.

Later on I tried to add a module to the dependency chain without adding it to the .uproject file, and it does get compiled and linked, but the module is never properly set up by FModuleManager. This encourages developers to always add module entries to the .uproject file, which in turn results in all modules being in all builds, unless explicitly blacklisted for a particular target/platform/configuration.

Here’s the summary:

Modules will always be complied and linked to the project:

  • If added to the .uproject file (or enabled .uplugin that the project depends on)
  • If they are in the dependency chain (wether they are a dependency of a module in the chain, or added to the ExtraModuleNames field of a .target.cs file)

However, here’s the caveat:
Modules will only be properly loaded and set up:

  • If they have a specified LoadingPhase in the .uproject file
  • If they are explicitly loaded by another module, via the FModuleManager class

This seems a bit unintuitive to me. Say I have a conditional dependency to a module, such as:

public MyGameTarget(TargetInfo Target) : base(Target)
{
    //...

    if(some condition...)
    {
        ExtraModuleNames.Add("MyModule");  	
    }

If I don’t want this module to be shipped along with my game, I can’t add it to the .uproject file. This means that I need to manually call FModuleManager::LoadModuleChecked("MyModule") from C++, which in turn means I need a condition in C++ to check wether or not the module should be loaded. Feels a bit cumbersome.

I feel like the only factor that should determine if modules go into builds is whether they are in the dependency chain. This would encourage me to add conditions to my .build.cs and .target.cs without worrying about the .uproject file bringing in all that unnecessary code into packaged builds.

Did that make sense? Do you agree? Have I done something wrong in my tests?