// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Xml;
using Tools.DotNETCommon.CaselessDictionary;
namespace UnrealBuildTool
{
///
/// A unit of code compilation and linking.
///
abstract class UEBuildModule
{
///
/// The name that uniquely identifies the module.
///
public readonly string Name;
///
/// The type of module being built. Used to switch between debug/development and precompiled/source configurations.
///
public UHTModuleType Type;
///
/// The rules for this module
///
public ModuleRules Rules;
///
/// Path to the module directory
///
public readonly DirectoryReference ModuleDirectory;
///
/// Is this module allowed to be redistributed.
///
private readonly bool? IsRedistributableOverride;
///
/// The name of the .Build.cs file this module was created from, if any
///
public FileReference RulesFile;
///
/// The binary the module will be linked into for the current target. Only set after UEBuildBinary.BindModules is called.
///
public UEBuildBinary Binary = null;
///
/// Include path for this module's base directory, relative to the Engine/Source directory
///
protected string NormalizedModuleIncludePath;
///
/// The name of the _API define for this module
///
protected readonly string ModuleApiDefine;
///
/// Set of all the public definitions
///
protected readonly HashSet PublicDefinitions;
///
/// Set of all public include paths
///
protected readonly HashSet PublicIncludePaths;
///
/// Set of all private include paths
///
protected readonly HashSet PrivateIncludePaths;
///
/// Set of all system include paths
///
protected readonly HashSet PublicSystemIncludePaths;
///
/// Set of all public library paths
///
protected readonly HashSet PublicLibraryPaths;
///
/// Set of all additional libraries
///
protected readonly HashSet PublicAdditionalLibraries;
///
/// Set of additional frameworks
///
protected readonly HashSet PublicFrameworks;
///
///
///
protected readonly HashSet PublicWeakFrameworks;
///
///
///
protected readonly HashSet PublicAdditionalFrameworks;
///
///
///
protected readonly HashSet PublicAdditionalShadowFiles;
///
///
///
protected readonly HashSet PublicAdditionalBundleResources;
///
/// Names of modules with header files that this module's public interface needs access to.
///
protected List PublicIncludePathModules;
///
/// Names of modules that this module's public interface depends on.
///
protected List PublicDependencyModules;
///
/// Names of DLLs that this module should delay load
///
protected HashSet PublicDelayLoadDLLs;
///
/// Names of modules with header files that this module's private implementation needs access to.
///
protected List PrivateIncludePathModules;
///
/// Names of modules that this module's private implementation depends on.
///
protected List PrivateDependencyModules;
///
/// Extra modules this module may require at run time
///
protected List DynamicallyLoadedModules;
///
/// Extra modules this module may require at run time, that are on behalf of another platform (i.e. shader formats and the like)
///
protected List PlatformSpecificDynamicallyLoadedModules;
///
/// Files which this module depends on at runtime.
///
public RuntimeDependencyList RuntimeDependencies;
///
/// Set of all whitelisted restricted folder references
///
private readonly HashSet WhitelistRestrictedFolders;
///
/// Constructor
///
/// Name of the module
/// Type of the module, for UHT
/// Base directory for the module
/// Rules for this module
/// Path to the rules file
public UEBuildModule(string InName, UHTModuleType InType, DirectoryReference InModuleDirectory, ModuleRules InRules, FileReference InRulesFile)
{
Name = InName;
Type = InType;
ModuleDirectory = InModuleDirectory;
Rules = InRules;
RulesFile = InRulesFile;
NormalizedModuleIncludePath = Utils.CleanDirectorySeparators(ModuleDirectory.MakeRelativeTo(UnrealBuildTool.EngineSourceDirectory), '/');
ModuleApiDefine = Name.ToUpperInvariant() + "_API";
PublicDefinitions = HashSetFromOptionalEnumerableStringParameter(InRules.Definitions);
PublicIncludePaths = HashSetFromOptionalEnumerableStringParameter(InRules.PublicIncludePaths);
PublicSystemIncludePaths = HashSetFromOptionalEnumerableStringParameter(InRules.PublicSystemIncludePaths);
PublicLibraryPaths = HashSetFromOptionalEnumerableStringParameter(InRules.PublicLibraryPaths);
PublicAdditionalLibraries = HashSetFromOptionalEnumerableStringParameter(InRules.PublicAdditionalLibraries);
PublicFrameworks = HashSetFromOptionalEnumerableStringParameter(InRules.PublicFrameworks);
PublicWeakFrameworks = HashSetFromOptionalEnumerableStringParameter(InRules.PublicWeakFrameworks);
PublicAdditionalFrameworks = InRules.PublicAdditionalFrameworks == null ? new HashSet() : new HashSet(InRules.PublicAdditionalFrameworks);
PublicAdditionalShadowFiles = HashSetFromOptionalEnumerableStringParameter(InRules.PublicAdditionalShadowFiles);
PublicAdditionalBundleResources = InRules.AdditionalBundleResources == null ? new HashSet() : new HashSet(InRules.AdditionalBundleResources);
PublicDelayLoadDLLs = HashSetFromOptionalEnumerableStringParameter(InRules.PublicDelayLoadDLLs);
PrivateIncludePaths = HashSetFromOptionalEnumerableStringParameter(InRules.PrivateIncludePaths);
RuntimeDependencies = (InRules.RuntimeDependencies == null) ? new RuntimeDependencyList() : new RuntimeDependencyList(InRules.RuntimeDependencies);
IsRedistributableOverride = InRules.IsRedistributableOverride;
WhitelistRestrictedFolders = new HashSet(InRules.WhitelistRestrictedFolders.Select(x => DirectoryReference.Combine(ModuleDirectory, x)));
}
///
/// Returns a list of this module's dependencies.
///
/// An enumerable containing the dependencies of the module.
public HashSet GetDependencies(bool bWithIncludePathModules, bool bWithDynamicallyLoadedModules)
{
HashSet Modules = new HashSet();
Modules.UnionWith(PublicDependencyModules);
Modules.UnionWith(PrivateDependencyModules);
if(bWithIncludePathModules)
{
Modules.UnionWith(PublicIncludePathModules);
Modules.UnionWith(PrivateIncludePathModules);
}
if(bWithDynamicallyLoadedModules)
{
Modules.UnionWith(DynamicallyLoadedModules);
Modules.UnionWith(PlatformSpecificDynamicallyLoadedModules);
}
return Modules;
}
///
/// Returns a list of this module's immediate dependencies.
///
/// An enumerable containing the dependencies of the module.
public IEnumerable GetDirectDependencyModules()
{
return PublicDependencyModules.Concat(PrivateDependencyModules).Concat(DynamicallyLoadedModules).Concat(PlatformSpecificDynamicallyLoadedModules);
}
///
/// Converts an optional string list parameter to a well-defined hash set.
///
protected static HashSet HashSetFromOptionalEnumerableStringParameter(IEnumerable InEnumerableStrings)
{
return InEnumerableStrings == null ? new HashSet() : new HashSet(InEnumerableStrings);
}
///
/// Determines whether this module has a circular dependency on the given module
///
public bool HasCircularDependencyOn(string ModuleName)
{
return Rules.CircularlyReferencedDependentModules.Contains(ModuleName);
}
///
/// Enumerates additional build products which may be produced by this module. Some platforms (eg. Mac, Linux) can link directly against .so/.dylibs, but they
/// are also copied to the output folder by the toolchain.
///
/// List to which libraries required by this module are added
/// List of bundle resources required by this module
public void GatherAdditionalResources(List Libraries, List BundleResources)
{
Libraries.AddRange(PublicAdditionalLibraries);
BundleResources.AddRange(PublicAdditionalBundleResources);
}
///
/// Determines the distribution level of a module based on its directory and includes.
///
/// The project directory, if available
/// Map of the restricted folder types to the first found instance
public Dictionary FindRestrictedFolderReferences(DirectoryReference ProjectDir)
{
Dictionary References = new Dictionary();
if (!Rules.bOutputPubliclyDistributable)
{
// Find all the directories that this module references
HashSet ReferencedDirs = new HashSet();
GetReferencedDirectories(ReferencedDirs);
// Remove all the whitelisted folders
ReferencedDirs.ExceptWith(WhitelistRestrictedFolders);
ReferencedDirs.ExceptWith(PublicDependencyModules.SelectMany(x => x.WhitelistRestrictedFolders));
ReferencedDirs.ExceptWith(PrivateDependencyModules.SelectMany(x => x.WhitelistRestrictedFolders));
// Add flags for each of them
foreach(DirectoryReference ReferencedDir in ReferencedDirs)
{
// Find the base directory containing this reference
DirectoryReference BaseDir;
if(ReferencedDir.IsUnderDirectory(UnrealBuildTool.EngineDirectory))
{
BaseDir = UnrealBuildTool.EngineDirectory;
}
else if(ProjectDir != null && ReferencedDir.IsUnderDirectory(ProjectDir))
{
BaseDir = ProjectDir;
}
else
{
continue;
}
// Add references to each of the restricted folders
List Folders = RestrictedFolders.FindRestrictedFolders(BaseDir, ReferencedDir);
foreach(RestrictedFolder Folder in Folders)
{
if(!References.ContainsKey(Folder))
{
References.Add(Folder, ReferencedDir);
}
}
}
}
return References;
}
///
/// Finds all the directories that this folder references when building
///
/// Set of directories to add to
protected virtual void GetReferencedDirectories(HashSet Directories)
{
Directories.Add(ModuleDirectory);
foreach(string PublicIncludePath in PublicIncludePaths)
{
Directories.Add(new DirectoryReference(PublicIncludePath));
}
foreach(string PrivateIncludePath in PrivateIncludePaths)
{
Directories.Add(new DirectoryReference(PrivateIncludePath));
}
foreach(string PublicSystemIncludePath in PublicSystemIncludePaths)
{
Directories.Add(new DirectoryReference(PublicSystemIncludePath));
}
foreach(string PublicLibraryPath in PublicLibraryPaths)
{
Directories.Add(new DirectoryReference(PublicLibraryPath));
}
}
///
/// Find all the modules which affect the public compile environment. Searches through
///
///
///
protected void FindModulesInPublicCompileEnvironment(List Modules, Dictionary ModuleToIncludePathsOnlyFlag)
{
//
bool bModuleIncludePathsOnly;
if (!ModuleToIncludePathsOnlyFlag.TryGetValue(this, out bModuleIncludePathsOnly))
{
Modules.Add(this);
}
else if (!bModuleIncludePathsOnly)
{
return;
}
ModuleToIncludePathsOnlyFlag[this] = false;
foreach (UEBuildModule DependencyModule in PublicDependencyModules)
{
DependencyModule.FindModulesInPublicCompileEnvironment(Modules, ModuleToIncludePathsOnlyFlag);
}
// Now add an include paths from modules with header files that we need access to, but won't necessarily be importing
foreach (UEBuildModule IncludePathModule in PublicIncludePathModules)
{
IncludePathModule.FindIncludePathModulesInPublicCompileEnvironment(Modules, ModuleToIncludePathsOnlyFlag);
}
}
///
/// Find all the modules which affect the public compile environment. Searches through
///
///
///
protected void FindIncludePathModulesInPublicCompileEnvironment(List Modules, Dictionary ModuleToIncludePathsOnlyFlag)
{
if (!ModuleToIncludePathsOnlyFlag.ContainsKey(this))
{
// Add this module to the list
Modules.Add(this);
ModuleToIncludePathsOnlyFlag.Add(this, true);
// Include any of its public include path modules in the compile environment too
foreach (UEBuildModule IncludePathModule in PublicIncludePathModules)
{
IncludePathModule.FindIncludePathModulesInPublicCompileEnvironment(Modules, ModuleToIncludePathsOnlyFlag);
}
}
}
///
/// Sets up the environment for compiling any module that includes the public interface of this module.
///
public void AddModuleToCompileEnvironment(
UEBuildBinary SourceBinary,
bool bIncludePathsOnly,
HashSet IncludePaths,
HashSet SystemIncludePaths,
List Definitions,
List AdditionalFrameworks
)
{
// Add this module's public include paths and definitions.
AddIncludePathsWithChecks(IncludePaths, PublicIncludePaths);
AddIncludePathsWithChecks(SystemIncludePaths, PublicSystemIncludePaths);
Definitions.AddRange(PublicDefinitions);
// If this module is being built into a DLL or EXE, set up an IMPORTS or EXPORTS definition for it.
if(SourceBinary == null)
{
// No source binary means a shared PCH, so always import all symbols. It's possible that an include path module now may be a imported module for the shared PCH consumer.
if(!bIncludePathsOnly)
{
if(Binary == null || !Binary.Config.bAllowExports)
{
Definitions.Add(ModuleApiDefine + "=");
}
else
{
Definitions.Add(ModuleApiDefine + "=DLLIMPORT");
}
}
}
else if (Binary == null)
{
// If we're referencing include paths for a module that's not being built, we don't actually need to import anything from it, but we need to avoid barfing when
// the compiler encounters an _API define. We also want to avoid changing the compile environment in cases where the module happens to be compiled because it's a dependency
// of something else, which cause a fall-through to the code below and set up an empty _API define.
if (bIncludePathsOnly)
{
Log.TraceVerbose("{0}: Include paths only for {1} (no binary)", SourceBinary.Config.OutputFilePaths[0].GetFileNameWithoutExtension(), Name);
Definitions.Add(ModuleApiDefine + "=");
}
}
else
{
FileReference BinaryPath = Binary.Config.OutputFilePaths[0];
FileReference SourceBinaryPath = SourceBinary.Config.OutputFilePaths[0];
if (ProjectFileGenerator.bGenerateProjectFiles || (Binary.Config.Type == UEBuildBinaryType.StaticLibrary))
{
// When generating IntelliSense files, never add dllimport/dllexport specifiers as it
// simply confuses the compiler
Definitions.Add(ModuleApiDefine + "=");
}
else if (Binary == SourceBinary)
{
if (Binary.Config.bAllowExports)
{
Log.TraceVerbose("{0}: Exporting {1} from {2}", SourceBinaryPath.GetFileNameWithoutExtension(), Name, BinaryPath.GetFileNameWithoutExtension());
Definitions.Add(ModuleApiDefine + "=DLLEXPORT");
}
else
{
Log.TraceVerbose("{0}: Not importing/exporting {1} (binary: {2})", SourceBinaryPath.GetFileNameWithoutExtension(), Name, BinaryPath.GetFileNameWithoutExtension());
Definitions.Add(ModuleApiDefine + "=");
}
}
else
{
// @todo SharedPCH: Public headers included from modules that are not importing the module of that public header, seems invalid.
// Those public headers have no business having APIs in them. OnlineSubsystem has some public headers like this. Without changing
// this, we need to suppress warnings at compile time.
if (bIncludePathsOnly)
{
Log.TraceVerbose("{0}: Include paths only for {1} (binary: {2})", SourceBinaryPath.GetFileNameWithoutExtension(), Name, BinaryPath.GetFileNameWithoutExtension());
Definitions.Add(ModuleApiDefine + "=");
}
else if (Binary.Config.bAllowExports)
{
Log.TraceVerbose("{0}: Importing {1} from {2}", SourceBinaryPath.GetFileNameWithoutExtension(), Name, BinaryPath.GetFileNameWithoutExtension());
Definitions.Add(ModuleApiDefine + "=DLLIMPORT");
}
else
{
Log.TraceVerbose("{0}: Not importing/exporting {1} (binary: {2})", SourceBinaryPath.GetFileNameWithoutExtension(), Name, BinaryPath.GetFileNameWithoutExtension());
Definitions.Add(ModuleApiDefine + "=");
}
}
}
// Add the module's directory to the include path, so we can root #includes to it
IncludePaths.Add(NormalizedModuleIncludePath);
// Add the additional frameworks so that the compiler can know about their #include paths
AdditionalFrameworks.AddRange(PublicAdditionalFrameworks);
// Remember the module so we can refer to it when needed
foreach (UEBuildFramework Framework in PublicAdditionalFrameworks)
{
Framework.OwningModule = this;
}
}
static Regex VCMacroRegex = new Regex(@"\$\([A-Za-z0-9_]+\)");
///
/// Checks if path contains a VC macro
///
protected bool DoesPathContainVCMacro(string Path)
{
return VCMacroRegex.IsMatch(Path);
}
///
/// Adds PathsToAdd to IncludePaths, performing path normalization and ignoring duplicates.
///
protected void AddIncludePathsWithChecks(HashSet IncludePaths, HashSet PathsToAdd)
{
if (ProjectFileGenerator.bGenerateProjectFiles)
{
// Extra checks are switched off for IntelliSense generation as they provide
// no additional value and cause performance impact.
IncludePaths.UnionWith(PathsToAdd);
}
else
{
foreach (string Path in PathsToAdd)
{
string NormalizedPath = Path.TrimEnd('/');
// If path doesn't exist, it may contain VC macro (which is passed directly to and expanded by compiler).
if (Directory.Exists(NormalizedPath) || DoesPathContainVCMacro(NormalizedPath))
{
IncludePaths.Add(NormalizedPath);
}
}
}
}
///
/// Sets up the environment for compiling this module.
///
protected virtual void SetupPrivateCompileEnvironment(
HashSet IncludePaths,
HashSet SystemIncludePaths,
List Definitions,
List AdditionalFrameworks
)
{
HashSet VisitedModules = new HashSet();
if (this.Type.IsGameModule())
{
Definitions.Add("DEPRECATED_FORGAME=DEPRECATED");
}
// Add this module's private include paths and definitions.
AddIncludePathsWithChecks(IncludePaths, PrivateIncludePaths);
// Find all the modules that are part of the public compile environment for this module.
List Modules = new List();
Dictionary ModuleToIncludePathsOnlyFlag = new Dictionary();
FindModulesInPublicCompileEnvironment(Modules, ModuleToIncludePathsOnlyFlag);
// Add in all the modules that are private dependencies
foreach (UEBuildModule DependencyModule in PrivateDependencyModules)
{
DependencyModule.FindModulesInPublicCompileEnvironment(Modules, ModuleToIncludePathsOnlyFlag);
}
// And finally add in all the modules that are include path only dependencies
foreach (UEBuildModule IncludePathModule in PrivateIncludePathModules)
{
IncludePathModule.FindIncludePathModulesInPublicCompileEnvironment(Modules, ModuleToIncludePathsOnlyFlag);
}
// Now set up the compile environment for the modules in the original order that we encountered them
foreach (UEBuildModule Module in Modules)
{
Module.AddModuleToCompileEnvironment(Binary, ModuleToIncludePathsOnlyFlag[Module], IncludePaths, SystemIncludePaths, Definitions, AdditionalFrameworks);
}
}
///
/// Sets up the environment for linking any module that includes the public interface of this module.
///
protected virtual void SetupPublicLinkEnvironment(
UEBuildBinary SourceBinary,
List LibraryPaths,
List AdditionalLibraries,
List Frameworks,
List WeakFrameworks,
List AdditionalFrameworks,
List AdditionalShadowFiles,
List AdditionalBundleResources,
List DelayLoadDLLs,
List BinaryDependencies,
HashSet VisitedModules
)
{
// There may be circular dependencies in compile dependencies, so we need to avoid reentrance.
if (VisitedModules.Add(this))
{
// Add this module's binary to the binary dependencies.
if (Binary != null
&& Binary != SourceBinary
&& !BinaryDependencies.Contains(Binary))
{
BinaryDependencies.Add(Binary);
}
// If this module belongs to a static library that we are not currently building, recursively add the link environment settings for all of its dependencies too.
// Keep doing this until we reach a module that is not part of a static library (or external module, since they have no associated binary).
// Static libraries do not contain the symbols for their dependencies, so we need to recursively gather them to be linked into other binary types.
bool bIsBuildingAStaticLibrary = (SourceBinary != null && SourceBinary.Config.Type == UEBuildBinaryType.StaticLibrary);
bool bIsModuleBinaryAStaticLibrary = (Binary != null && Binary.Config.Type == UEBuildBinaryType.StaticLibrary);
if (!bIsBuildingAStaticLibrary && bIsModuleBinaryAStaticLibrary)
{
// Gather all dependencies and recursively call SetupPublicLinkEnvironmnet
List AllDependencyModules = new List();
AllDependencyModules.AddRange(PrivateDependencyModules);
AllDependencyModules.AddRange(PublicDependencyModules);
foreach (UEBuildModule DependencyModule in AllDependencyModules)
{
bool bIsExternalModule = (DependencyModule as UEBuildModuleExternal != null);
bool bIsInStaticLibrary = (DependencyModule.Binary != null && DependencyModule.Binary.Config.Type == UEBuildBinaryType.StaticLibrary);
if (bIsExternalModule || bIsInStaticLibrary)
{
DependencyModule.SetupPublicLinkEnvironment(SourceBinary, LibraryPaths, AdditionalLibraries, Frameworks, WeakFrameworks,
AdditionalFrameworks, AdditionalShadowFiles, AdditionalBundleResources, DelayLoadDLLs, BinaryDependencies, VisitedModules);
}
}
}
// Add this module's public include library paths and additional libraries.
LibraryPaths.AddRange(PublicLibraryPaths);
AdditionalLibraries.AddRange(PublicAdditionalLibraries);
Frameworks.AddRange(PublicFrameworks);
WeakFrameworks.AddRange(PublicWeakFrameworks);
AdditionalBundleResources.AddRange(PublicAdditionalBundleResources);
// Remember the module so we can refer to it when needed
foreach (UEBuildFramework Framework in PublicAdditionalFrameworks)
{
Framework.OwningModule = this;
}
AdditionalFrameworks.AddRange(PublicAdditionalFrameworks);
AdditionalShadowFiles.AddRange(PublicAdditionalShadowFiles);
DelayLoadDLLs.AddRange(PublicDelayLoadDLLs);
}
}
///
/// Sets up the environment for linking this module.
///
public virtual void SetupPrivateLinkEnvironment(
UEBuildBinary SourceBinary,
LinkEnvironment LinkEnvironment,
List BinaryDependencies,
HashSet VisitedModules
)
{
// Allow the module's public dependencies to add library paths and additional libraries to the link environment.
SetupPublicLinkEnvironment(SourceBinary, LinkEnvironment.LibraryPaths, LinkEnvironment.AdditionalLibraries, LinkEnvironment.Frameworks, LinkEnvironment.WeakFrameworks,
LinkEnvironment.AdditionalFrameworks, LinkEnvironment.AdditionalShadowFiles, LinkEnvironment.AdditionalBundleResources, LinkEnvironment.DelayLoadDLLs, BinaryDependencies, VisitedModules);
// Also allow the module's public and private dependencies to modify the link environment.
List AllDependencyModules = new List();
AllDependencyModules.AddRange(PrivateDependencyModules);
AllDependencyModules.AddRange(PublicDependencyModules);
foreach (UEBuildModule DependencyModule in AllDependencyModules)
{
DependencyModule.SetupPublicLinkEnvironment(SourceBinary, LinkEnvironment.LibraryPaths, LinkEnvironment.AdditionalLibraries, LinkEnvironment.Frameworks, LinkEnvironment.WeakFrameworks,
LinkEnvironment.AdditionalFrameworks, LinkEnvironment.AdditionalShadowFiles, LinkEnvironment.AdditionalBundleResources, LinkEnvironment.DelayLoadDLLs, BinaryDependencies, VisitedModules);
}
}
///
/// Compiles the module, and returns a list of files output by the compiler.
///
public abstract List Compile(ReadOnlyTargetRules Target, UEToolChain ToolChain, CppCompileEnvironment CompileEnvironment, List SharedPCHModules, ActionGraph ActionGraph);
// Object interface.
public override string ToString()
{
return Name;
}
///
/// Finds the modules referenced by this module which have not yet been bound to a binary
///
/// List of unbound modules
public List GetUnboundReferences()
{
List Modules = new List();
Modules.AddRange(PrivateDependencyModules.Where(x => x.Binary == null));
Modules.AddRange(PublicDependencyModules.Where(x => x.Binary == null));
return Modules;
}
///
/// Gets all of the modules referenced by this module
///
/// Hash of all referenced modules with their addition index.
/// Hashset used to ignore modules which are already added to the list
/// True if dynamically loaded modules (and all of their dependent modules) should be included.
/// True if circular dependencies should be processed
/// True to return only this module's direct dependencies
public virtual void GetAllDependencyModules(List ReferencedModules, HashSet IgnoreReferencedModules, bool bIncludeDynamicallyLoaded, bool bForceCircular, bool bOnlyDirectDependencies)
{
}
///
/// Gets all of the modules precompiled along with this module
///
/// Set of all the precompiled modules
public virtual void RecursivelyAddPrecompiledModules(List Modules)
{
}
public delegate UEBuildModule CreateModuleDelegate(string Name);
///
/// Creates all the modules required for this target
///
public void RecursivelyCreateModules(CreateModuleDelegate CreateModule)
{
// Create all the include path modules. These modules may not be added to the target (and we don't process their dependencies), but they need
// to be created to set up their compile environment.
RecursivelyCreateIncludePathModulesByName(Rules.PublicIncludePathModuleNames, ref PublicIncludePathModules, CreateModule);
RecursivelyCreateIncludePathModulesByName(Rules.PrivateIncludePathModuleNames, ref PrivateIncludePathModules, CreateModule);
// Create all the dependency modules
RecursivelyCreateModulesByName(Rules.PublicDependencyModuleNames, ref PublicDependencyModules, CreateModule);
RecursivelyCreateModulesByName(Rules.PrivateDependencyModuleNames, ref PrivateDependencyModules, CreateModule);
RecursivelyCreateModulesByName(Rules.DynamicallyLoadedModuleNames, ref DynamicallyLoadedModules, CreateModule);
RecursivelyCreateModulesByName(Rules.PlatformSpecificDynamicallyLoadedModuleNames, ref PlatformSpecificDynamicallyLoadedModules, CreateModule);
}
private static void RecursivelyCreateModulesByName(List ModuleNames, ref List Modules, CreateModuleDelegate CreateModule)
{
// Check whether the module list is already set. We set this immediately (via the ref) to avoid infinite recursion.
if (Modules == null)
{
Modules = new List();
foreach (string ModuleName in ModuleNames)
{
UEBuildModule Module = CreateModule(ModuleName);
if (!Modules.Contains(Module))
{
Module.RecursivelyCreateModules(CreateModule);
Modules.Add(Module);
}
}
}
}
private static void RecursivelyCreateIncludePathModulesByName(List ModuleNames, ref List Modules, CreateModuleDelegate CreateModule)
{
// Check whether the module list is already set. We set this immediately (via the ref) to avoid infinite recursion.
if (Modules == null)
{
Modules = new List();
foreach (string ModuleName in ModuleNames)
{
UEBuildModule Module = CreateModule(ModuleName);
RecursivelyCreateIncludePathModulesByName(Module.Rules.PublicIncludePathModuleNames, ref Module.PublicIncludePathModules, CreateModule);
Modules.Add(Module);
}
}
}
///
/// Write information about this binary to a JSON file
///
/// Writer for this binary's data
public virtual void ExportJson(JsonWriter Writer)
{
Writer.WriteValue("Name", Name);
Writer.WriteValue("Type", Type.ToString());
Writer.WriteValue("Directory", ModuleDirectory.FullName);
Writer.WriteValue("Rules", RulesFile.FullName);
Writer.WriteValue("PCHUsage", Rules.PCHUsage.ToString());
if (Rules.PrivatePCHHeaderFile != null)
{
Writer.WriteValue("PrivatePCH", FileReference.Combine(ModuleDirectory, Rules.PrivatePCHHeaderFile).FullName);
}
if (Rules.SharedPCHHeaderFile != null)
{
Writer.WriteValue("SharedPCH", FileReference.Combine(ModuleDirectory, Rules.SharedPCHHeaderFile).FullName);
}
ExportJsonModuleArray(Writer, "PublicDependencyModules", PublicDependencyModules);
ExportJsonModuleArray(Writer, "PublicIncludePathModules", PublicIncludePathModules);
ExportJsonModuleArray(Writer, "PrivateDependencyModules", PrivateDependencyModules);
ExportJsonModuleArray(Writer, "PrivateIncludePathModules", PrivateIncludePathModules);
ExportJsonModuleArray(Writer, "DynamicallyLoadedModules", DynamicallyLoadedModules);
Writer.WriteArrayStart("CircularlyReferencedModules");
foreach(string ModuleName in Rules.CircularlyReferencedDependentModules)
{
Writer.WriteValue(ModuleName);
}
Writer.WriteArrayEnd();
Writer.WriteArrayStart("RuntimeDependencies");
foreach(RuntimeDependency RuntimeDependency in Rules.RuntimeDependencies)
{
Writer.WriteObjectStart();
Writer.WriteValue("Path", RuntimeDependency.Path);
Writer.WriteValue("Type", RuntimeDependency.Type.ToString());
Writer.WriteObjectEnd();
}
Writer.WriteArrayEnd();
}
///
/// Write an array of module names to a JSON writer
///
/// Writer for the array data
/// Name of the array property
/// Sequence of modules to write. May be null.
void ExportJsonModuleArray(JsonWriter Writer, string ArrayName, IEnumerable Modules)
{
Writer.WriteArrayStart(ArrayName);
if (Modules != null)
{
foreach (UEBuildModule Module in Modules)
{
Writer.WriteValue(Module.Name);
}
}
Writer.WriteArrayEnd();
}
};
}