/// <summary> /// Adds a binary for the given module. Does not check whether a binary already exists, or whether a binary should be created for this build configuration. /// </summary> /// <param name="ModuleName">Name of the binary</param> /// <param name="BinaryType">Type of binary to be created</param> /// <param name="bAllowCompilation">Whether this binary can be compiled. The function will check whether plugin binaries can be compiled.</param> /// <param name="bIsCrossTarget">True if module is for supporting a different target-platform</param> /// <returns>The new binary</returns> private UEBuildBinaryCPP AddBinaryForModule(string ModuleName, UEBuildBinaryType BinaryType, bool bAllowCompilation, bool bIsCrossTarget) { // Get the plugin info for this module PluginInfo Plugin = FindPluginForModule(ModuleName); // Get the root output directory and base name (target name/app name) for this binary string BaseOutputDirectory; if(Plugin != null) { BaseOutputDirectory = Path.GetFullPath(Plugin.Directory); } else if(RulesCompiler.IsGameModule(ModuleName) || !bUseSharedBuildEnvironment) { BaseOutputDirectory = Path.GetFullPath(ProjectDirectory); } else { BaseOutputDirectory = Path.GetFullPath(BuildConfiguration.RelativeEnginePath); } // Get the configuration that this module will be built in. Engine modules compiled in DebugGame will use Development. UnrealTargetConfiguration ModuleConfiguration = Configuration; if(Configuration == UnrealTargetConfiguration.DebugGame && !RulesCompiler.IsGameModule(ModuleName)) { ModuleConfiguration = UnrealTargetConfiguration.Development; } // Get the output and intermediate directories for this module string OutputDirectory = Path.Combine(BaseOutputDirectory, "Binaries", Platform.ToString()); string IntermediateDirectory = Path.Combine(BaseOutputDirectory, BuildConfiguration.PlatformIntermediateFolder, AppName, ModuleConfiguration.ToString()); // Append a subdirectory if the module rules specifies one ModuleRules ModuleRules; if(RulesCompiler.TryCreateModuleRules(ModuleName, TargetInfo, out ModuleRules) && !String.IsNullOrEmpty(ModuleRules.BinariesSubFolder)) { OutputDirectory = Path.Combine(OutputDirectory, ModuleRules.BinariesSubFolder); IntermediateDirectory = Path.Combine(IntermediateDirectory, ModuleRules.BinariesSubFolder); } // Get the output filenames string BaseBinaryPath = Path.Combine(OutputDirectory, MakeBinaryFileName(AppName + "-" + ModuleName, Platform, ModuleConfiguration, Rules.UndecoratedConfiguration, BinaryType)); string[] OutputFilePaths = UEBuildPlatform.GetBuildPlatform(Platform).FinalizeBinaryPaths(BaseBinaryPath); // Prepare the configuration object UEBuildBinaryConfiguration Config = new UEBuildBinaryConfiguration(BinaryType); Config.OutputFilePaths = OutputFilePaths; Config.IntermediateDirectory = IntermediateDirectory; Config.bHasModuleRules = (ModuleRules != null); Config.bAllowExports = (BinaryType == UEBuildBinaryType.DynamicLinkLibrary); Config.bAllowCompilation = bAllowCompilation; Config.bIsCrossTarget = bIsCrossTarget; Config.ModuleNames.Add(ModuleName); // Create the new binary UEBuildBinaryCPP Binary = new UEBuildBinaryCPP(this, Config); AppBinaries.Add(Binary); return Binary; }
public override void RecursivelyProcessUnboundModules(UEBuildTarget Target, ref Dictionary<string, UEBuildBinary> Binaries, UEBuildBinary ExecutableBinary) { // Make sure this module is bound to a binary if( !bIncludedInTarget ) { throw new BuildException( "Module '{0}' should already have been bound to a binary!", Name ); } var AllModuleNames = new List<string>(); AllModuleNames.AddRange( PrivateDependencyModuleNames ); AllModuleNames.AddRange( PublicDependencyModuleNames ); AllModuleNames.AddRange( DynamicallyLoadedModuleNames ); AllModuleNames.AddRange( PlatformSpecificDynamicallyLoadedModuleNames ); foreach( var DependencyName in AllModuleNames ) { var DependencyModule = Target.FindOrCreateModuleByName(DependencyName); // Skip modules that are included with the target (externals) if( !DependencyModule.bIncludedInTarget ) { if( !Binaries.ContainsKey( DependencyModule.Name ) ) { UEBuildBinary BinaryToBindTo; if (Target.ShouldCompileMonolithic()) { // When linking monolithically, any unbound modules will be linked into the main executable BinaryToBindTo = ExecutableBinary; } else { // Is this a Rocket module? bool bIsRocketModule = RulesCompiler.IsRocketProjectModule(DependencyName); // Is this a plugin module? var PluginInfo = Plugins.GetPluginInfoForModule( DependencyName ); string OutputFilePath = Target.MakeBinaryPath(DependencyModule.Name, Target.GetAppName() + "-" + DependencyModule.Name, UEBuildBinaryType.DynamicLinkLibrary, Target.Rules.Type, bIsRocketModule, PluginInfo, ""); // If it's an engine module, output intermediates to the engine intermediates directory. string IntermediateDirectory = Binary.Config.IntermediateDirectory; if (PluginInfo == null && IntermediateDirectory != Target.EngineIntermediateDirectory && Path.GetFullPath(DependencyModule.ModuleDirectory).StartsWith(Path.GetFullPath(BuildConfiguration.RelativeEnginePath))) { IntermediateDirectory = Target.EngineIntermediateDirectory; } // When using modular linkage, unbound modules will be linked into their own DLL files UEBuildBinaryConfiguration Config = new UEBuildBinaryConfiguration( InType: UEBuildBinaryType.DynamicLinkLibrary, InOutputFilePath: OutputFilePath, InIntermediateDirectory: IntermediateDirectory, bInAllowExports: true, InModuleNames: new List<string> { DependencyModule.Name }, InTargetName: Target.GetAppName(), bInIsCrossTarget: PlatformSpecificDynamicallyLoadedModuleNames.Contains(DependencyName) && !DynamicallyLoadedModuleNames.Contains(DependencyName), InTargetConfiguration: Target.Configuration, bInCompileMonolithic: Target.ShouldCompileMonolithic() ); // Fix up the binary path if this is module specifies an alternate output directory Config.OutputFilePath = DependencyModule.FixupOutputPath(Config.OutputFilePath); BinaryToBindTo = new UEBuildBinaryCPP( Target, Config ); } Binaries[ DependencyModule.Name ] = BinaryToBindTo; // Bind this module DependencyModule.Binary = BinaryToBindTo; DependencyModule.bIncludedInTarget = true; // Also add binaries for this module's dependencies DependencyModule.RecursivelyProcessUnboundModules( Target, ref Binaries, ExecutableBinary ); } } if (Target.ShouldCompileMonolithic() == false) { // Check to see if there is a circular relationship between the module and it's referencer if( DependencyModule.Binary != null ) { if( CircularlyReferencedDependentModules.Contains( DependencyName ) ) { DependencyModule.Binary.SetCreateImportLibrarySeparately( true ); } } } } // Also make sure module entries are created for any module that is pulled in as an "include path" module. // These modules are never linked in unless they were referenced as an actual dependency of a different module, // but we still need to keep track of them so that we can find their include paths when setting up our // module's include paths. RecursivelyAddIncludePathModules( Target, bPublicIncludesOnly:false ); }