UnrealEngine provides its own module system, which is absolutely different with CPP 20 Module. The class UnrealBuildTool.ModuleRules is for the module system and it is written by [ModuleName].Build.cs. You can decide what to include for creating output files (= DLL). For example, ShaderCompileWorker project has the module rules below:
There are several libraries such as Core, Projects, RenderCore and so on. We can also find them in Binaries folder like below: (FYI, the ShaderCompileWorker.exe is created with ShaderCompileWorker.Target.cs not the ShaderCompileWorker.Build.cs.)
In other words, output files are created with the name containing its module when you add corresponding libraries to module rules (ex: [TargetName]-[ModuleName]-[ConfigurationName].dll). Additionally, UnrealEngine re-uses them as possible. Suppose your project need some libraries already included on engine side. In this situation, UnrealEngine does not create output files for the duplicated libraries included in your project. Instead of that, UnrealEngine leaves some meta file describes what the project included.
1 2 3 4 5 6 7 8 9 10 11 12 13
// Copyright Epic Games, Inc. All Rights Reserved.
This is a generated module rules based on third person template. This module rules contains CoreUObject library but we cannot find it in Binaries folder. Let us see the ThirdPerson_4_25Editor.target file.
For more details about the module system, visit reference #1.
UnrealBuildTool.TargetRules
UnrealEngine provides its own target system, which makes you can create an executable. There are various target configurations such as Editor, Client and Server. The class UnrealBuildTool.TargetRules is for the target system and it is written by [TargetName].Target.cs. You can decide which modules to include for a certain target. For example, UE4 project has the target rules for editor below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// Copyright Epic Games, Inc. All Rights Reserved.
using UnrealBuildTool; using System.Collections.Generic;
The target rules specifies UE4Game module included, which is located in Engine/Source/Runtime/UE4Game. So, output files for editor are consist of modules in UE4Game.
...csharp ///<summary> /// TargetRules is a data structure that contains the rules for defining a target (application/executable) ///</summary> publicabstractpartialclassTargetRules { ... ///<summary> /// The type of target. ///</summary> publicglobal::UnrealBuildTool.TargetType Type = global::UnrealBuildTool.TargetType.Game; ...
The field is used for branching target-specific features such as build configuration. For example, UnrealEngine manages target configurations as enum.
... ///<summary> /// The type of configuration a target can be built for ///</summary> publicenum UnrealTargetConfiguration { ///<summary> /// Unknown ///</summary> Unknown,
... ///<summary> /// Gets a list of configurations that this target supports ///</summary> ///<returns>Array of configurations that the target supports</returns> internal UnrealTargetConfiguration[] GetSupportedConfigurations() { // Otherwise take the SupportedConfigurationsAttribute from the first type in the inheritance chain that supports it for (Type CurrentType = GetType(); CurrentType != null; CurrentType = CurrentType.BaseType) { object[] Attributes = CurrentType.GetCustomAttributes(typeof(SupportedConfigurationsAttribute), false); if (Attributes.Length > 0) { return Attributes.OfType<SupportedConfigurationsAttribute>().SelectMany(x => x.Configurations).Distinct().ToArray(); } }
// Otherwise, get the default for the target type if (Type == TargetType.Editor) { returnnew[] { UnrealTargetConfiguration.Debug, UnrealTargetConfiguration.DebugGame, UnrealTargetConfiguration.Development }; } else { return ((UnrealTargetConfiguration[])Enum.GetValues(typeof(UnrealTargetConfiguration))).Where(x => x != UnrealTargetConfiguration.Unknown).ToArray(); } } ...
Each module has its own Build.cs file. For example, a [ProjectName].Build.cs will be generated when you create new project with cpp enabled. Because UnrealEngine makes a default module that has the same name with project. (Exactly, Build.cs and Target.cs files are copied from template in general cases.)
// Discover and copy all files in the src folder to the destination, excluding a few files and folders TArray<FString> FilesToCopy; TArray<FString> FilesThatNeedContentsReplaced; TMap<FString, FString> ClassRenames; IFileManager::Get().FindFilesRecursive(FilesToCopy, *SrcFolder, TEXT("*"), /*Files=*/true, /*Directories=*/false);
if ( ReplacementsInFilesExtensions.Contains(FileExtension) ) { FilesThatNeedContentsReplaced.Add(DestFilename); }
// Allow project template to extract class renames from this file copy if (FPaths::GetBaseFilename(SrcFilename) != FPaths::GetBaseFilename(DestFilename) && TemplateDefs->IsClassRename(DestFilename, SrcFilename, FileExtension)) { // Looks like a UObject file! ClassRenames.Add(FPaths::GetBaseFilename(SrcFilename), FPaths::GetBaseFilename(DestFilename)); } } ...
WHEN YOU CREATE A PROJECT ITS NAME OF ThridPerson_4_25 FROM THIRD PERSON TEMPLATE
Saying that again, [ModuleName].Build.cs defines the dependencies for building its module. So, every module must have its own [ModuleName].Build.cs file and every module has its own [ModuleName].Build.cs will generate a DLL when you build the project.
While every module must have a Build.cs file, but every module do not have to have a Target.cs file. Some modules have only Build.cs file. It means the modules should be used for library not a standalone. The AIModule is a good example. The module has only Build.cs as it is written for providing a support to make AI.
... if (Target.bBuildEditor == true) { PublicDependencyModuleNames.AddRange( newstring[] { "UnrealEd", "Kismet" } ); // @todo api: Only public because of WITH_EDITOR and UNREALED_API ...
Sometimes, some modules should not be included on certain target configurations. For instance, only editor features should not be included in client or server target configuration. In the need, we can branch for ease like below:
... // Editor builds include SessionServices to populate the remote target drop-down for remote widget snapshots if (Target.Type == TargetType.Editor) { PublicDefinitions.Add("SLATE_REFLECTOR_HAS_SESSION_SERVICES=1");
We can use Widget Relfector only at editor target configuration. As we see, non-editor target will not contain the reflector feature. One more step, we can force to block generating projects by throwing an exception like this.