/// <summary> /// Builds the binary. /// </summary> /// <param name="CompileEnvironment">The environment to compile the binary in</param> /// <param name="LinkEnvironment">The environment to link the binary in</param> /// <returns></returns> public override IEnumerable <FileItem> Build(IUEToolChain TargetToolChain, CPPEnvironment CompileEnvironment, LinkEnvironment LinkEnvironment) { // Determine the type of binary we're linking. switch (Config.Type) { case UEBuildBinaryType.DynamicLinkLibrary: CompileEnvironment.Config.bIsBuildingDLL = true; CompileEnvironment.Config.bIsBuildingLibrary = false; break; case UEBuildBinaryType.StaticLibrary: CompileEnvironment.Config.bIsBuildingDLL = false; CompileEnvironment.Config.bIsBuildingLibrary = true; break; default: CompileEnvironment.Config.bIsBuildingDLL = false; CompileEnvironment.Config.bIsBuildingLibrary = false; break; } ; var OutputFiles = new List <FileItem>(); var BinaryCompileEnvironment = CompileEnvironment.DeepCopy(); var BinaryLinkEnvironment = LinkEnvironment.DeepCopy(); // Process each module that is linked into the binary. var BinaryDependencies = new List <UEBuildBinary>(); var LinkEnvironmentVisitedModules = new Dictionary <UEBuildModule, bool>(); // @Hack: This to prevent UHT from listing CoreUObject.generated.cpp as its dependency. // We flag the compile environment when we build UHT so that we don't need to check // this for each file when generating their dependencies. BinaryCompileEnvironment.bHackHeaderGenerator = (Target.GetAppName() == "UnrealHeaderTool"); // @todo: This should be in some Windows code somewhere... // Set the original file name macro; used in PCLaunch.rc to set the binary metadata fields. var OriginalFilename = (Config.OriginalOutputFilePaths != null) ? Path.GetFileName(Config.OriginalOutputFilePaths[0]) : Path.GetFileName(Config.OutputFilePaths[0]); BinaryCompileEnvironment.Config.Definitions.Add("ORIGINAL_FILE_NAME=\"" + OriginalFilename + "\""); foreach (var ModuleName in ModuleNames) { var Module = Target.GetModuleByName(ModuleName); // Compile each module. Log.TraceVerbose("Compile module: " + ModuleName); var LinkInputFiles = Module.Compile(CompileEnvironment, BinaryCompileEnvironment, Config.bCompileMonolithic); // NOTE: Because of 'Shared PCHs', in monolithic builds the same PCH file may appear as a link input // multiple times for a single binary. We'll check for that here, and only add it once. This avoids // a linker warning about redundant .obj files. foreach (var LinkInputFile in LinkInputFiles) { if (!BinaryLinkEnvironment.InputFiles.Contains(LinkInputFile)) { BinaryLinkEnvironment.InputFiles.Add(LinkInputFile); } } // Allow the module to modify the link environment for the binary. Module.SetupPrivateLinkEnvironment(ref BinaryLinkEnvironment, ref BinaryDependencies, ref LinkEnvironmentVisitedModules); } // Remove the default resource file on Windows (PCLaunch.rc) if the user has specified their own if (BinaryLinkEnvironment.InputFiles.Select(Item => Path.GetFileName(Item.AbsolutePath).ToLower()).Any(Name => Name.EndsWith(".res") && !Name.EndsWith(".inl.res") && Name != "pclaunch.rc.res")) { BinaryLinkEnvironment.InputFiles.RemoveAll(x => Path.GetFileName(x.AbsolutePath).ToLower() == "pclaunch.rc.res"); } // Allow the binary dependencies to modify the link environment. foreach (var BinaryDependency in BinaryDependencies) { BinaryDependency.SetupDependentLinkEnvironment(ref BinaryLinkEnvironment); } // Set the link output file. BinaryLinkEnvironment.Config.OutputFilePaths = Config.OutputFilePaths != null ? (string[])Config.OutputFilePaths.Clone() : null; // Set whether the link is allowed to have exports. BinaryLinkEnvironment.Config.bHasExports = Config.bAllowExports; // Set the output folder for intermediate files BinaryLinkEnvironment.Config.IntermediateDirectory = Config.IntermediateDirectory; // Put the non-executable output files (PDB, import library, etc) in the same directory as the production BinaryLinkEnvironment.Config.OutputDirectory = Path.GetDirectoryName(Config.OutputFilePaths[0]); // Determine the type of binary we're linking. switch (Config.Type) { case UEBuildBinaryType.DynamicLinkLibrary: BinaryLinkEnvironment.Config.bIsBuildingDLL = true; BinaryLinkEnvironment.Config.bIsBuildingLibrary = false; break; case UEBuildBinaryType.StaticLibrary: BinaryLinkEnvironment.Config.bIsBuildingDLL = false; BinaryLinkEnvironment.Config.bIsBuildingLibrary = true; break; default: BinaryLinkEnvironment.Config.bIsBuildingDLL = false; BinaryLinkEnvironment.Config.bIsBuildingLibrary = false; break; } ; if (ProjectFileGenerator.bGenerateProjectFiles) { // We're generating projects. Since we only need include paths and definitions, there is no need // to go ahead and run through the linking logic. OutputFiles = BinaryLinkEnvironment.InputFiles; } else if (BuildConfiguration.bEnableCodeAnalysis) { // We're only analyzing code, so we won't actually link any executables. Instead, our output // files will simply be the .obj files that were compiled during static analysis. OutputFiles = BinaryLinkEnvironment.InputFiles; } else { if (bCreateImportLibrarySeparately) { // Mark the link environment as cross-referenced. BinaryLinkEnvironment.Config.bIsCrossReferenced = true; if (BinaryLinkEnvironment.Config.Target.Platform != CPPTargetPlatform.Mac && BinaryLinkEnvironment.Config.Target.Platform != CPPTargetPlatform.Linux) { // Create the import library. OutputFiles.AddRange(BinaryLinkEnvironment.LinkExecutable(true)); } } BinaryLinkEnvironment.Config.bIncludeDependentLibrariesInLibrary = bIncludeDependentLibrariesInLibrary; // Link the binary. FileItem[] Executables = BinaryLinkEnvironment.LinkExecutable(false); OutputFiles.AddRange(Executables); // Produce additional console app if requested if (BinaryLinkEnvironment.Config.CanProduceAdditionalConsoleApp && UEBuildConfiguration.bBuildEditor) { // Produce additional binary but link it as a console app var ConsoleAppLinkEvironment = BinaryLinkEnvironment.DeepCopy(); ConsoleAppLinkEvironment.Config.bIsBuildingConsoleApplication = true; ConsoleAppLinkEvironment.Config.WindowsEntryPointOverride = "WinMainCRTStartup"; // For WinMain() instead of "main()" for Launch module for (int Index = 0; Index < Config.OutputFilePaths.Length; Index++) { ConsoleAppLinkEvironment.Config.OutputFilePaths[Index] = GetAdditionalConsoleAppPath(ConsoleAppLinkEvironment.Config.OutputFilePaths[Index]); } // Link the console app executable OutputFiles.AddRange(ConsoleAppLinkEvironment.LinkExecutable(false)); } foreach (var Executable in Executables) { OutputFiles.AddRange(TargetToolChain.PostBuild(Executable, BinaryLinkEnvironment)); } } return(OutputFiles); }
// UEBuildModule interface. public override List<FileItem> Compile( CPPEnvironment GlobalCompileEnvironment, CPPEnvironment CompileEnvironment ) { var ModuleCLREnvironment = CompileEnvironment.DeepCopy(); // Setup the module environment for the project CLR mode ModuleCLREnvironment.Config.CLRMode = CPPCLRMode.CLREnabled; // Add the private assembly references to the compile environment. foreach(var PrivateAssemblyReference in PrivateAssemblyReferences) { ModuleCLREnvironment.AddPrivateAssembly(PrivateAssemblyReference); } // Pass the CLR compilation environment to the standard C++ module compilation code. return base.Compile(GlobalCompileEnvironment, ModuleCLREnvironment ); }
private LinkEnvironment SetupBinaryLinkEnvironment(LinkEnvironment LinkEnvironment, CPPEnvironment CompileEnvironment) { var BinaryLinkEnvironment = LinkEnvironment.DeepCopy(); var LinkEnvironmentVisitedModules = new Dictionary <UEBuildModule, bool>(); var BinaryDependencies = new List <UEBuildBinary>(); CompileEnvironment.Config.bIsBuildingDLL = IsBuildingDll(Config.Type); CompileEnvironment.Config.bIsBuildingLibrary = IsBuildingLibrary(Config.Type); var BinaryCompileEnvironment = CompileEnvironment.DeepCopy(); // @Hack: This to prevent UHT from listing CoreUObject.generated.cpp as its dependency. // We flag the compile environment when we build UHT so that we don't need to check // this for each file when generating their dependencies. BinaryCompileEnvironment.bHackHeaderGenerator = (Target.GetAppName() == "UnrealHeaderTool"); // @todo: This should be in some Windows code somewhere... // Set the original file name macro; used in PCLaunch.rc to set the binary metadata fields. var OriginalFilename = (Config.OriginalOutputFilePaths != null) ? Path.GetFileName(Config.OriginalOutputFilePaths[0]) : Path.GetFileName(Config.OutputFilePaths[0]); BinaryCompileEnvironment.Config.Definitions.Add("ORIGINAL_FILE_NAME=\"" + OriginalFilename + "\""); foreach (var ModuleName in ModuleNames) { var Module = Target.GetModuleByName(ModuleName); List <FileItem> LinkInputFiles; if (Module.Binary == null || Module.Binary == this) { // Compile each module. Log.TraceVerbose("Compile module: " + ModuleName); LinkInputFiles = Module.Compile(CompileEnvironment, BinaryCompileEnvironment); // NOTE: Because of 'Shared PCHs', in monolithic builds the same PCH file may appear as a link input // multiple times for a single binary. We'll check for that here, and only add it once. This avoids // a linker warning about redundant .obj files. foreach (var LinkInputFile in LinkInputFiles) { if (!BinaryLinkEnvironment.InputFiles.Contains(LinkInputFile)) { BinaryLinkEnvironment.InputFiles.Add(LinkInputFile); } } } else { BinaryDependencies.Add(Module.Binary); } if (!BuildConfiguration.bRunUnrealCodeAnalyzer) { // Allow the module to modify the link environment for the binary. Module.SetupPrivateLinkEnvironment(this, BinaryLinkEnvironment, BinaryDependencies, LinkEnvironmentVisitedModules); } } // Allow the binary dependencies to modify the link environment. foreach (var BinaryDependency in BinaryDependencies) { BinaryDependency.SetupDependentLinkEnvironment(BinaryLinkEnvironment); } // Remove the default resource file on Windows (PCLaunch.rc) if the user has specified their own if (BinaryLinkEnvironment.InputFiles.Select(Item => Path.GetFileName(Item.AbsolutePath).ToLower()).Any(Name => Name.EndsWith(".res") && !Name.EndsWith(".inl.res") && Name != "pclaunch.rc.res")) { BinaryLinkEnvironment.InputFiles.RemoveAll(x => Path.GetFileName(x.AbsolutePath).ToLower() == "pclaunch.rc.res"); } // Set the link output file. BinaryLinkEnvironment.Config.OutputFilePaths = Config.OutputFilePaths.ToList(); // Set whether the link is allowed to have exports. BinaryLinkEnvironment.Config.bHasExports = Config.bAllowExports; // Set the output folder for intermediate files BinaryLinkEnvironment.Config.IntermediateDirectory = Config.IntermediateDirectory; // Put the non-executable output files (PDB, import library, etc) in the same directory as the production BinaryLinkEnvironment.Config.OutputDirectory = Path.GetDirectoryName(Config.OutputFilePaths[0]); // Setup link output type BinaryLinkEnvironment.Config.bIsBuildingDLL = IsBuildingDll(Config.Type); BinaryLinkEnvironment.Config.bIsBuildingLibrary = IsBuildingLibrary(Config.Type); return(BinaryLinkEnvironment); }
// UEBuildModule interface. public override List<FileItem> Compile(CPPEnvironment GlobalCompileEnvironment, CPPEnvironment CompileEnvironment) { var BuildPlatform = UEBuildPlatform.GetBuildPlatformForCPPTargetPlatform(CompileEnvironment.Config.Target.Platform); var LinkInputFiles = new List<FileItem>(); if( ProjectFileGenerator.bGenerateProjectFiles && IntelliSenseGatherer == null) { // Nothing to do for IntelliSense, bail out early return LinkInputFiles; } var ModuleCompileEnvironment = CreateModuleCompileEnvironment(CompileEnvironment); IncludeSearchPaths = ModuleCompileEnvironment.Config.CPPIncludeInfo.IncludePaths.ToList(); IncludeSearchPaths.AddRange(ModuleCompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths.ToList()); if( IntelliSenseGatherer != null ) { // Update project file's set of preprocessor definitions and include paths IntelliSenseGatherer.AddIntelliSensePreprocessorDefinitions( ModuleCompileEnvironment.Config.Definitions ); IntelliSenseGatherer.AddInteliiSenseIncludePaths( ModuleCompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths, bAddingSystemIncludes: true ); IntelliSenseGatherer.AddInteliiSenseIncludePaths( ModuleCompileEnvironment.Config.CPPIncludeInfo.IncludePaths, bAddingSystemIncludes: false ); // Bail out. We don't need to actually compile anything while generating project files. return LinkInputFiles; } // Throw an error if the module's source file list referenced any non-existent files. if (SourceFilesToBuild.MissingFiles.Count > 0) { throw new BuildException( "UBT ERROR: Module \"{0}\" references non-existent files:\n{1} (perhaps a file was added to the project but not checked in)", Name, string.Join("\n", SourceFilesToBuild.MissingFiles.Select(M => M.AbsolutePath)) ); } // For an executable or a static library do not use the default RC file - // If the executable wants it, it will be in their source list anyway. // The issue here is that when making a monolithic game, the processing // of the other game modules will stomp the game-specific rc file. if (Binary.Config.Type == UEBuildBinaryType.DynamicLinkLibrary) { // Add default PCLaunch.rc file if this module has no own resource file specified if (SourceFilesToBuild.RCFiles.Count <= 0) { string DefRC = Utils.CleanDirectorySeparators( Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), "Runtime/Launch/Resources/Windows/PCLaunch.rc")) ); FileItem Item = FileItem.GetItemByFullPath(DefRC); SourceFilesToBuild.RCFiles.Add(Item); } // Always compile in the API version resource separately. This is required for the module manager to detect compatible API versions. string ModuleVersionRC = Utils.CleanDirectorySeparators( Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), "Runtime/Core/Resources/Windows/ModuleVersionResource.rc.inl")) ); FileItem ModuleVersionItem = FileItem.GetItemByFullPath(ModuleVersionRC); if( !SourceFilesToBuild.RCFiles.Contains(ModuleVersionItem) ) { SourceFilesToBuild.RCFiles.Add(ModuleVersionItem); } } { // Process all of the header file dependencies for this module this.CachePCHUsageForModuleSourceFiles( ModuleCompileEnvironment ); // Make sure our RC files have cached includes. foreach( var RCFile in SourceFilesToBuild.RCFiles ) { RCFile.CachedCPPIncludeInfo = ModuleCompileEnvironment.Config.CPPIncludeInfo; } } // Check to see if this is an Engine module (including program or plugin modules). That is, the module is located under the "Engine" folder var IsGameModule = !Utils.IsFileUnderDirectory( this.ModuleDirectory, Path.Combine( ProjectFileGenerator.EngineRelativePath ) ); // Should we force a precompiled header to be generated for this module? Usually, we only bother with a // precompiled header if there are at least several source files in the module (after combining them for unity // builds.) But for game modules, it can be convenient to always have a precompiled header to single-file // changes to code is really quick to compile. int MinFilesUsingPrecompiledHeader = BuildConfiguration.MinFilesUsingPrecompiledHeader; if( MinFilesUsingPrecompiledHeaderOverride != 0 ) { MinFilesUsingPrecompiledHeader = MinFilesUsingPrecompiledHeaderOverride; } else if( IsGameModule && BuildConfiguration.bForcePrecompiledHeaderForGameModules ) { // This is a game module with only a small number of source files, so go ahead and force a precompiled header // to be generated to make incremental changes to source files as fast as possible for small projects. MinFilesUsingPrecompiledHeader = 1; } // Should we use unity build mode for this module? bool bModuleUsesUnityBuild = BuildConfiguration.bUseUnityBuild || BuildConfiguration.bForceUnityBuild; if (!BuildConfiguration.bForceUnityBuild) { if (bFasterWithoutUnity) { bModuleUsesUnityBuild = false; } else if (IsGameModule && SourceFilesToBuild.CPPFiles.Count < BuildConfiguration.MinGameModuleSourceFilesForUnityBuild) { // Game modules with only a small number of source files are usually better off having faster iteration times // on single source file changes, so we forcibly disable unity build for those modules bModuleUsesUnityBuild = false; } } // The environment with which to compile the CPP files var CPPCompileEnvironment = ModuleCompileEnvironment; // Precompiled header support. bool bWasModuleCodeCompiled = false; if (BuildPlatform.ShouldUsePCHFiles(CompileEnvironment.Config.Target.Platform, CompileEnvironment.Config.Target.Configuration)) { var PCHGenTimerStart = DateTime.UtcNow; // The code below will figure out whether this module will either use a "unique PCH" (private PCH that will only be included by // this module's code files), or a "shared PCH" (potentially included by many code files in many modules.) Only one or the other // will be used. FileItem SharedPCHHeaderFile = null; // In the case of a shared PCH, we also need to keep track of which module that PCH's header file is a member of string SharedPCHModuleName = String.Empty; if( BuildConfiguration.bUseSharedPCHs && CompileEnvironment.Config.bIsBuildingLibrary ) { Log.TraceVerbose("Module '{0}' was not allowed to use Shared PCHs, because we're compiling to a library", this.Name ); } bool bUseSharedPCHFiles = BuildConfiguration.bUseSharedPCHs && !CompileEnvironment.Config.bIsBuildingLibrary && GlobalCompileEnvironment.SharedPCHHeaderFiles.Count > 0; if( bUseSharedPCHFiles ) { string SharingPCHHeaderFilePath = null; bool bIsASharedPCHModule = bUseSharedPCHFiles && GlobalCompileEnvironment.SharedPCHHeaderFiles.Any( PCH => PCH.Module == this ); if( bIsASharedPCHModule ) { SharingPCHHeaderFilePath = Path.GetFullPath( Path.Combine( ProjectFileGenerator.RootRelativePath, "Engine", "Source", this.SharedPCHHeaderFile ) ); } // We can't use a shared PCH file when compiling a module // with exports, because the shared PCH can only have imports in it to work correctly. bool bCanModuleUseOwnSharedPCH = bAllowSharedPCH && bIsASharedPCHModule && !Binary.Config.bAllowExports && ProcessedDependencies.UniquePCHHeaderFile.AbsolutePath.Equals( SharingPCHHeaderFilePath, StringComparison.InvariantCultureIgnoreCase ); if( bAllowSharedPCH && ( !bIsASharedPCHModule || bCanModuleUseOwnSharedPCH ) ) { // Figure out which shared PCH tier we're in var ReferencedModules = new CaselessDictionary<ModuleIndexPair>(); { this.GetAllDependencyModules( ReferencedModules, bIncludeDynamicallyLoaded:false, bForceCircular:false, bOnlyDirectDependencies:true ); } int LargestSharedPCHHeaderFileIndex = -1; foreach( var DependencyModule in ReferencedModules.Values.OrderBy(P => P.Index).Select(P => P.Module) ) { // These Shared PCHs are ordered from least complex to most complex. We'll start at the last one and search backwards. for( var SharedPCHHeaderFileIndex = GlobalCompileEnvironment.SharedPCHHeaderFiles.Count - 1; SharedPCHHeaderFileIndex > LargestSharedPCHHeaderFileIndex; --SharedPCHHeaderFileIndex ) { var CurSharedPCHHeaderFile = GlobalCompileEnvironment.SharedPCHHeaderFiles[ SharedPCHHeaderFileIndex ]; if( DependencyModule == CurSharedPCHHeaderFile.Module || ( bIsASharedPCHModule && CurSharedPCHHeaderFile.Module == this ) ) // If we ourselves are a shared PCH module, always at least use our own module as our shared PCH header if we can't find anything better { SharedPCHModuleName = CurSharedPCHHeaderFile.Module.Name; SharedPCHHeaderFile = CurSharedPCHHeaderFile.PCHHeaderFile; LargestSharedPCHHeaderFileIndex = SharedPCHHeaderFileIndex; break; } } if( LargestSharedPCHHeaderFileIndex == GlobalCompileEnvironment.SharedPCHHeaderFiles.Count - 1 ) { // We've determined that the module is using our most complex PCH header, so we can early-out break; } } // Did we not find a shared PCH header that is being included by this module? This could happen if the module is not including Core.h, even indirectly. if( String.IsNullOrEmpty( SharedPCHModuleName ) ) { throw new BuildException( "Module {0} doesn't use a Shared PCH! Please add a dependency on a Shared PCH module to this module's dependency list", this.Name); } // Keep track of how many modules make use of this PCH for performance diagnostics var LargestSharedPCHHeader = GlobalCompileEnvironment.SharedPCHHeaderFiles[ LargestSharedPCHHeaderFileIndex ]; ++LargestSharedPCHHeader.NumModulesUsingThisPCH; } else { Log.TraceVerbose("Module '{0}' cannot create or use Shared PCHs, because it needs its own private PCH", this.Name); } } // The precompiled header environment for all source files in this module that use a precompiled header, if we even need one PrecompileHeaderEnvironment ModulePCHEnvironment = null; // If there was one header that was included first by enough C++ files, use it as the precompiled header. // Only use precompiled headers for projects with enough files to make the PCH creation worthwhile. if( SharedPCHHeaderFile != null || SourceFilesToBuild.CPPFiles.Count >= MinFilesUsingPrecompiledHeader ) { FileItem PCHToUse; if( SharedPCHHeaderFile != null ) { ModulePCHEnvironment = ApplySharedPCH(GlobalCompileEnvironment, CompileEnvironment, ModuleCompileEnvironment, SourceFilesToBuild.CPPFiles, ref SharedPCHHeaderFile); if (ModulePCHEnvironment != null) { // @todo SharedPCH: Ideally we would exhaustively check for a compatible compile environment (definitions, imports/exports, etc) // Currently, it's possible for the shared PCH to be compiled differently depending on which module UBT happened to have // include it first during the build phase. This could create problems with deterministic builds, or turn up compile // errors unexpectedly due to compile environment differences. Log.TraceVerbose("Module " + Name + " uses existing Shared PCH '" + ModulePCHEnvironment.PrecompiledHeaderIncludeFilename + "' (from module " + ModulePCHEnvironment.ModuleName + ")"); } PCHToUse = SharedPCHHeaderFile; } else { PCHToUse = ProcessedDependencies.UniquePCHHeaderFile; } if (PCHToUse != null) { // Update all CPPFiles to point to the PCH foreach (var CPPFile in SourceFilesToBuild.CPPFiles) { CPPFile.PCHHeaderNameInCode = PCHToUse.AbsolutePath; CPPFile.PrecompiledHeaderIncludeFilename = PCHToUse.AbsolutePath; } } // A shared PCH was not already set up for us, so set one up. if( ModulePCHEnvironment == null ) { var PCHHeaderFile = ProcessedDependencies.UniquePCHHeaderFile; var PCHModuleName = this.Name; if( SharedPCHHeaderFile != null ) { PCHHeaderFile = SharedPCHHeaderFile; PCHModuleName = SharedPCHModuleName; } var PCHHeaderNameInCode = SourceFilesToBuild.CPPFiles[ 0 ].PCHHeaderNameInCode; ModulePCHEnvironment = new PrecompileHeaderEnvironment( PCHModuleName, PCHHeaderNameInCode, PCHHeaderFile, ModuleCompileEnvironment.Config.CLRMode, ModuleCompileEnvironment.Config.OptimizeCode ); if( SharedPCHHeaderFile != null ) { // Add to list of shared PCH environments GlobalCompileEnvironment.SharedPCHEnvironments.Add( ModulePCHEnvironment ); Log.TraceVerbose( "Module " + Name + " uses new Shared PCH '" + ModulePCHEnvironment.PrecompiledHeaderIncludeFilename + "'" ); } else { Log.TraceVerbose( "Module " + Name + " uses a Unique PCH '" + ModulePCHEnvironment.PrecompiledHeaderIncludeFilename + "'" ); } } } else { Log.TraceVerbose( "Module " + Name + " doesn't use a Shared PCH, and only has " + SourceFilesToBuild.CPPFiles.Count.ToString() + " source file(s). No Unique PCH will be generated." ); } // Compile the C++ source or the unity C++ files that use a PCH environment. if( ModulePCHEnvironment != null ) { // Setup a new compile environment for this module's source files. It's pretty much the exact same as the // module's compile environment, except that it will include a PCH file. var ModulePCHCompileEnvironment = ModuleCompileEnvironment.DeepCopy(); ModulePCHCompileEnvironment.Config.PrecompiledHeaderAction = PrecompiledHeaderAction.Include; ModulePCHCompileEnvironment.Config.PrecompiledHeaderIncludeFilename = ModulePCHEnvironment.PrecompiledHeaderIncludeFilename.AbsolutePath; ModulePCHCompileEnvironment.Config.PCHHeaderNameInCode = ModulePCHEnvironment.PCHHeaderNameInCode; if( SharedPCHHeaderFile != null ) { // Shared PCH headers need to be force included, because we're basically forcing the module to use // the precompiled header that we want, instead of the "first include" in each respective .cpp file ModulePCHCompileEnvironment.Config.bForceIncludePrecompiledHeader = true; } var CPPFilesToBuild = SourceFilesToBuild.CPPFiles; if (bModuleUsesUnityBuild) { // unity files generated for only the set of files which share the same PCH environment CPPFilesToBuild = Unity.GenerateUnityCPPs( Target, CPPFilesToBuild, ModulePCHCompileEnvironment, Name ); } // Check if there are enough unity files to warrant pch generation (and we haven't already generated the shared one) if( ModulePCHEnvironment.PrecompiledHeaderFile == null ) { if( SharedPCHHeaderFile != null || CPPFilesToBuild.Count >= MinFilesUsingPrecompiledHeader ) { CPPOutput PCHOutput; if (SharedPCHHeaderFile == null) { PCHOutput = PrecompileHeaderEnvironment.GeneratePCHCreationAction( Target, CPPFilesToBuild[0].PCHHeaderNameInCode, ModulePCHEnvironment.PrecompiledHeaderIncludeFilename, ModuleCompileEnvironment, ModuleCompileEnvironment.Config.OutputDirectory, Name, true ); } else { UEBuildModuleCPP SharedPCHModule = (UEBuildModuleCPP)Target.FindOrCreateModuleByName(SharedPCHModuleName); CPPEnvironment SharedPCHCompileEnvironment = GlobalCompileEnvironment.DeepCopy(); SharedPCHCompileEnvironment.Config.bEnableShadowVariableWarning = SharedPCHModule.bEnableShadowVariableWarnings; SharedPCHModule.SetupPublicCompileEnvironment( Binary, false, SharedPCHCompileEnvironment.Config.CPPIncludeInfo.IncludePaths, SharedPCHCompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths, SharedPCHCompileEnvironment.Config.Definitions, SharedPCHCompileEnvironment.Config.AdditionalFrameworks, new Dictionary<UEBuildModule,bool>()); PCHOutput = PrecompileHeaderEnvironment.GeneratePCHCreationAction( Target, CPPFilesToBuild[0].PCHHeaderNameInCode, ModulePCHEnvironment.PrecompiledHeaderIncludeFilename, SharedPCHCompileEnvironment, Path.Combine( CompileEnvironment.Config.OutputDirectory, "SharedPCHs" ), "Shared", false ); } ModulePCHEnvironment.PrecompiledHeaderFile = PCHOutput.PrecompiledHeaderFile; ModulePCHEnvironment.OutputObjectFiles.Clear(); ModulePCHEnvironment.OutputObjectFiles.AddRange( PCHOutput.ObjectFiles ); } else if( CPPFilesToBuild.Count < MinFilesUsingPrecompiledHeader ) { Log.TraceVerbose( "Module " + Name + " doesn't use a Shared PCH, and only has " + CPPFilesToBuild.Count.ToString() + " unity source file(s). No Unique PCH will be generated." ); } } if( ModulePCHEnvironment.PrecompiledHeaderFile != null ) { // Link in the object files produced by creating the precompiled header. LinkInputFiles.AddRange( ModulePCHEnvironment.OutputObjectFiles ); // if pch action was generated for the environment then use pch ModulePCHCompileEnvironment.PrecompiledHeaderFile = ModulePCHEnvironment.PrecompiledHeaderFile; // Use this compile environment from now on CPPCompileEnvironment = ModulePCHCompileEnvironment; } LinkInputFiles.AddRange( CPPCompileEnvironment.CompileFiles( Target, CPPFilesToBuild, Name ).ObjectFiles ); bWasModuleCodeCompiled = true; } if( BuildConfiguration.bPrintPerformanceInfo ) { var PCHGenTime = ( DateTime.UtcNow - PCHGenTimerStart ).TotalSeconds; TotalPCHGenTime += PCHGenTime; } } if( !bWasModuleCodeCompiled && SourceFilesToBuild.CPPFiles.Count > 0 ) { var CPPFilesToCompile = SourceFilesToBuild.CPPFiles; if (bModuleUsesUnityBuild) { CPPFilesToCompile = Unity.GenerateUnityCPPs( Target, CPPFilesToCompile, CPPCompileEnvironment, Name ); } LinkInputFiles.AddRange( CPPCompileEnvironment.CompileFiles( Target, CPPFilesToCompile, Name ).ObjectFiles ); } if (AutoGenerateCppInfo != null && AutoGenerateCppInfo.BuildInfo != null && !CPPCompileEnvironment.bHackHeaderGenerator) { string[] GeneratedFiles = Directory.GetFiles(Path.GetDirectoryName(AutoGenerateCppInfo.BuildInfo.FileWildcard), Path.GetFileName(AutoGenerateCppInfo.BuildInfo.FileWildcard)); foreach (string GeneratedFilename in GeneratedFiles) { var GeneratedCppFileItem = FileItem.GetItemByPath(GeneratedFilename); CachePCHUsageForModuleSourceFile(this.Target, CPPCompileEnvironment, GeneratedCppFileItem); // @todo ubtmake: Check for ALL other places where we might be injecting .cpp or .rc files for compiling without caching CachedCPPIncludeInfo first (anything platform specific?) LinkInputFiles.AddRange(CPPCompileEnvironment.CompileFiles(Target, new List<FileItem> { GeneratedCppFileItem }, Name).ObjectFiles); } } // Compile C files directly. LinkInputFiles.AddRange(CPPCompileEnvironment.CompileFiles( Target, SourceFilesToBuild.CFiles, Name).ObjectFiles); // Compile CC files directly. LinkInputFiles.AddRange(CPPCompileEnvironment.CompileFiles( Target, SourceFilesToBuild.CCFiles, Name).ObjectFiles); // Compile MM files directly. LinkInputFiles.AddRange(CPPCompileEnvironment.CompileFiles( Target, SourceFilesToBuild.MMFiles, Name).ObjectFiles); // Compile RC files. LinkInputFiles.AddRange(CPPCompileEnvironment.CompileRCFiles(Target, SourceFilesToBuild.RCFiles).ObjectFiles); return LinkInputFiles; }
/// <summary> /// Creates a compile environment from a base environment based on the module settings. /// </summary> /// <param name="BaseCompileEnvironment">An existing environment to base the module compile environment on.</param> /// <returns>The new module compile environment.</returns> public CPPEnvironment CreateModuleCompileEnvironment(CPPEnvironment BaseCompileEnvironment) { var Result = BaseCompileEnvironment.DeepCopy(); // Override compile environment Result.Config.bFasterWithoutUnity = bFasterWithoutUnity; Result.Config.OptimizeCode = OptimizeCode; Result.Config.bUseRTTI = bUseRTTI; Result.Config.bUseAVX = bUseAVX; Result.Config.bEnableBufferSecurityChecks = bEnableBufferSecurityChecks; Result.Config.bFasterWithoutUnity = bFasterWithoutUnity; Result.Config.MinFilesUsingPrecompiledHeaderOverride = MinFilesUsingPrecompiledHeaderOverride; Result.Config.bBuildLocallyWithSNDBS = bBuildLocallyWithSNDBS; Result.Config.bEnableExceptions = bEnableExceptions; Result.Config.bEnableShadowVariableWarning = bEnableShadowVariableWarnings; Result.Config.bUseStaticCRT = (Target.Rules != null && Target.Rules.bUseStaticCRT); Result.Config.OutputDirectory = Path.Combine(Binary.Config.IntermediateDirectory, Name); // Switch the optimization flag if we're building a game module. Also pass the definition for building in DebugGame along (see ModuleManager.h for notes). if (Target.Configuration == UnrealTargetConfiguration.DebugGame) { if(!Utils.IsFileUnderDirectory(ModuleDirectory, BuildConfiguration.RelativeEnginePath)) { Result.Config.Target.Configuration = CPPTargetConfiguration.Debug; Result.Config.Definitions.Add("UE_BUILD_DEVELOPMENT_WITH_DEBUGGAME=1"); } } // Add the module's private definitions. Result.Config.Definitions.AddRange(Definitions); // Setup the compile environment for the module. SetupPrivateCompileEnvironment(Result.Config.CPPIncludeInfo.IncludePaths, Result.Config.CPPIncludeInfo.SystemIncludePaths, Result.Config.Definitions, Result.Config.AdditionalFrameworks); // @hack to skip adding definitions to compile environment, they will be baked into source code files if (bSkipDefinitionsForCompileEnvironment) { Result.Config.Definitions.Clear(); Result.Config.CPPIncludeInfo.IncludePaths = new HashSet<string>(BaseCompileEnvironment.Config.CPPIncludeInfo.IncludePaths); } return Result; }
/// <summary> /// Creates a precompiled header action to generate a new pch file /// </summary> /// <param name="PCHHeaderNameInCode">The precompiled header name as it appeared in an #include statement</param> /// <param name="PrecompiledHeaderIncludeFilename">Name of the header used for pch.</param> /// <param name="ProjectCPPEnvironment">The environment the C/C++ files in the project are compiled with.</param> /// <param name="OutputDirectory">The folder to save the generated PCH file to</param> /// <param name="ModuleName">Name of the module this PCH is being generated for</param> /// <param name="bAllowDLLExports">True if we should allow DLLEXPORT definitions for this PCH</param> /// <returns>the compilation output result of the created pch.</returns> public static CPPOutput GeneratePCHCreationAction(UEBuildTarget Target, string PCHHeaderNameInCode, FileItem PrecompiledHeaderIncludeFilename, CPPEnvironment ProjectCPPEnvironment, string OutputDirectory, string ModuleName, bool bAllowDLLExports ) { // Find the header file to be precompiled. Don't skip external headers if (PrecompiledHeaderIncludeFilename.bExists) { // Create a Dummy wrapper around the PCH to avoid problems with #pragma once on clang var ToolChain = UEToolChain.GetPlatformToolChain(ProjectCPPEnvironment.Config.Target.Platform); string PCHGuardDefine = Path.GetFileNameWithoutExtension(PrecompiledHeaderIncludeFilename.AbsolutePath).ToUpper(); string LocalPCHHeaderNameInCode = ToolChain.ConvertPath(PrecompiledHeaderIncludeFilename.AbsolutePath); string TmpPCHHeaderContents = String.Format("#ifndef __AUTO_{0}_H__\n#define __AUTO_{0}_H__\n//Last Write: {2}\n#include \"{1}\"\n#endif//__AUTO_{0}_H__", PCHGuardDefine, LocalPCHHeaderNameInCode, PrecompiledHeaderIncludeFilename.LastWriteTime); string DummyPath = Path.Combine( ProjectCPPEnvironment.Config.OutputDirectory, Path.GetFileName(PrecompiledHeaderIncludeFilename.AbsolutePath)); FileItem DummyPCH = FileItem.CreateIntermediateTextFile(DummyPath, TmpPCHHeaderContents); // Create a new C++ environment that is used to create the PCH. var ProjectPCHEnvironment = ProjectCPPEnvironment.DeepCopy(); ProjectPCHEnvironment.Config.PrecompiledHeaderAction = PrecompiledHeaderAction.Create; ProjectPCHEnvironment.Config.PrecompiledHeaderIncludeFilename = PrecompiledHeaderIncludeFilename.AbsolutePath; ProjectPCHEnvironment.Config.PCHHeaderNameInCode = PCHHeaderNameInCode; ProjectPCHEnvironment.Config.OutputDirectory = OutputDirectory; if( !bAllowDLLExports ) { for( var CurDefinitionIndex = 0; CurDefinitionIndex < ProjectPCHEnvironment.Config.Definitions.Count; ++CurDefinitionIndex ) { // We change DLLEXPORT to DLLIMPORT for "shared" PCH headers var OldDefinition = ProjectPCHEnvironment.Config.Definitions[ CurDefinitionIndex ]; if( OldDefinition.EndsWith( "=DLLEXPORT" ) ) { ProjectPCHEnvironment.Config.Definitions[ CurDefinitionIndex ] = OldDefinition.Replace( "DLLEXPORT", "DLLIMPORT" ); } } } // Cache our CPP environment so that we can check for outdatedness quickly. Only files that have includes need this. DummyPCH.CachedCPPIncludeInfo = ProjectPCHEnvironment.Config.CPPIncludeInfo; Log.TraceVerbose( "Found PCH file \"{0}\".", PrecompiledHeaderIncludeFilename ); // Create the action to compile the PCH file. return ProjectPCHEnvironment.CompileFiles(Target, new List<FileItem>() { DummyPCH }, ModuleName); } throw new BuildException( "Couldn't find PCH file \"{0}\".", PrecompiledHeaderIncludeFilename ); }
private LinkEnvironment SetupBinaryLinkEnvironment(LinkEnvironment LinkEnvironment, CPPEnvironment CompileEnvironment) { var BinaryLinkEnvironment = LinkEnvironment.DeepCopy(); var LinkEnvironmentVisitedModules = new Dictionary<UEBuildModule, bool>(); var BinaryDependencies = new List<UEBuildBinary>(); CompileEnvironment.Config.bIsBuildingDLL = IsBuildingDll(Config.Type); CompileEnvironment.Config.bIsBuildingLibrary = IsBuildingLibrary(Config.Type); var BinaryCompileEnvironment = CompileEnvironment.DeepCopy(); // @Hack: This to prevent UHT from listing CoreUObject.generated.cpp as its dependency. // We flag the compile environment when we build UHT so that we don't need to check // this for each file when generating their dependencies. BinaryCompileEnvironment.bHackHeaderGenerator = (Target.GetAppName() == "UnrealHeaderTool"); // @todo: This should be in some Windows code somewhere... // Set the original file name macro; used in PCLaunch.rc to set the binary metadata fields. var OriginalFilename = (Config.OriginalOutputFilePaths != null) ? Path.GetFileName(Config.OriginalOutputFilePaths[0]) : Path.GetFileName(Config.OutputFilePaths[0]); BinaryCompileEnvironment.Config.Definitions.Add("ORIGINAL_FILE_NAME=\"" + OriginalFilename + "\""); foreach (var ModuleName in ModuleNames) { var Module = Target.GetModuleByName(ModuleName); List<FileItem> LinkInputFiles; if(Module.Binary == null || Module.Binary == this) { // Compile each module. Log.TraceVerbose("Compile module: " + ModuleName); LinkInputFiles = Module.Compile(CompileEnvironment, BinaryCompileEnvironment); // NOTE: Because of 'Shared PCHs', in monolithic builds the same PCH file may appear as a link input // multiple times for a single binary. We'll check for that here, and only add it once. This avoids // a linker warning about redundant .obj files. foreach (var LinkInputFile in LinkInputFiles) { if (!BinaryLinkEnvironment.InputFiles.Contains(LinkInputFile)) { BinaryLinkEnvironment.InputFiles.Add(LinkInputFile); } } } else { BinaryDependencies.Add(Module.Binary); } if (!BuildConfiguration.bRunUnrealCodeAnalyzer) { // Allow the module to modify the link environment for the binary. Module.SetupPrivateLinkEnvironment(this, BinaryLinkEnvironment, BinaryDependencies, LinkEnvironmentVisitedModules); } } // Allow the binary dependencies to modify the link environment. foreach (var BinaryDependency in BinaryDependencies) { BinaryDependency.SetupDependentLinkEnvironment(BinaryLinkEnvironment); } // Remove the default resource file on Windows (PCLaunch.rc) if the user has specified their own if (BinaryLinkEnvironment.InputFiles.Select(Item => Path.GetFileName(Item.AbsolutePath).ToLower()).Any(Name => Name.EndsWith(".res") && !Name.EndsWith(".inl.res") && Name != "pclaunch.rc.res")) { BinaryLinkEnvironment.InputFiles.RemoveAll(x => Path.GetFileName(x.AbsolutePath).ToLower() == "pclaunch.rc.res"); } // Set the link output file. BinaryLinkEnvironment.Config.OutputFilePaths = Config.OutputFilePaths != null ? (string[])Config.OutputFilePaths.Clone() : null; // Set whether the link is allowed to have exports. BinaryLinkEnvironment.Config.bHasExports = Config.bAllowExports; // Set the output folder for intermediate files BinaryLinkEnvironment.Config.IntermediateDirectory = Config.IntermediateDirectory; // Put the non-executable output files (PDB, import library, etc) in the same directory as the production BinaryLinkEnvironment.Config.OutputDirectory = Path.GetDirectoryName(Config.OutputFilePaths[0]); // Setup link output type BinaryLinkEnvironment.Config.bIsBuildingDLL = IsBuildingDll(Config.Type); BinaryLinkEnvironment.Config.bIsBuildingLibrary = IsBuildingLibrary(Config.Type); return BinaryLinkEnvironment; }
private LinkEnvironment SetupBinaryLinkEnvironment(UEBuildTarget Target, UEToolChain ToolChain, LinkEnvironment LinkEnvironment, CPPEnvironment CompileEnvironment, List <PrecompiledHeaderTemplate> SharedPCHs, ActionGraph ActionGraph) { LinkEnvironment BinaryLinkEnvironment = LinkEnvironment.DeepCopy(); HashSet <UEBuildModule> LinkEnvironmentVisitedModules = new HashSet <UEBuildModule>(); List <UEBuildBinary> BinaryDependencies = new List <UEBuildBinary>(); CompileEnvironment.Config.bIsBuildingDLL = IsBuildingDll(Config.Type); CompileEnvironment.Config.bIsBuildingLibrary = IsBuildingLibrary(Config.Type); CPPEnvironment BinaryCompileEnvironment = CompileEnvironment.DeepCopy(); // @Hack: This to prevent UHT from listing CoreUObject.generated.cpp as its dependency. // We flag the compile environment when we build UHT so that we don't need to check // this for each file when generating their dependencies. BinaryCompileEnvironment.bHackHeaderGenerator = (Target.GetAppName() == "UnrealHeaderTool"); // @todo: This should be in some Windows code somewhere... // Set the original file name macro; used in PCLaunch.rc to set the binary metadata fields. string OriginalFilename = (Config.OriginalOutputFilePaths != null) ? Config.OriginalOutputFilePaths[0].GetFileName() : Config.OutputFilePaths[0].GetFileName(); BinaryCompileEnvironment.Config.Definitions.Add("ORIGINAL_FILE_NAME=\"" + OriginalFilename + "\""); foreach (UEBuildModule Module in Modules) { List <FileItem> LinkInputFiles; if (Module.Binary == null || Module.Binary == this) { // Compile each module. Log.TraceVerbose("Compile module: " + Module.Name); LinkInputFiles = Module.Compile(Target, ToolChain, BinaryCompileEnvironment, SharedPCHs, ActionGraph); // NOTE: Because of 'Shared PCHs', in monolithic builds the same PCH file may appear as a link input // multiple times for a single binary. We'll check for that here, and only add it once. This avoids // a linker warning about redundant .obj files. foreach (FileItem LinkInputFile in LinkInputFiles) { if (!BinaryLinkEnvironment.InputFiles.Contains(LinkInputFile)) { BinaryLinkEnvironment.InputFiles.Add(LinkInputFile); } } } else { BinaryDependencies.Add(Module.Binary); } if (!BuildConfiguration.bRunUnrealCodeAnalyzer) { // Allow the module to modify the link environment for the binary. Module.SetupPrivateLinkEnvironment(this, BinaryLinkEnvironment, BinaryDependencies, LinkEnvironmentVisitedModules); } } // Allow the binary dependencies to modify the link environment. foreach (UEBuildBinary BinaryDependency in BinaryDependencies) { BinaryDependency.SetupDependentLinkEnvironment(BinaryLinkEnvironment); } // Remove the default resource file on Windows (PCLaunch.rc) if the user has specified their own if (BinaryLinkEnvironment.InputFiles.Select(Item => Path.GetFileName(Item.AbsolutePath).ToLower()).Any(Name => Name.EndsWith(".res") && !Name.EndsWith(".inl.res") && Name != "pclaunch.rc.res")) { BinaryLinkEnvironment.InputFiles.RemoveAll(x => Path.GetFileName(x.AbsolutePath).ToLower() == "pclaunch.rc.res"); } // Set the link output file. BinaryLinkEnvironment.Config.OutputFilePaths = Config.OutputFilePaths.ToList(); // Set whether the link is allowed to have exports. BinaryLinkEnvironment.Config.bHasExports = Config.bAllowExports; // Set the output folder for intermediate files BinaryLinkEnvironment.Config.IntermediateDirectory = Config.IntermediateDirectory; // Put the non-executable output files (PDB, import library, etc) in the same directory as the production BinaryLinkEnvironment.Config.OutputDirectory = Config.OutputFilePaths[0].Directory; // Setup link output type BinaryLinkEnvironment.Config.bIsBuildingDLL = IsBuildingDll(Config.Type); BinaryLinkEnvironment.Config.bIsBuildingLibrary = IsBuildingLibrary(Config.Type); BinaryLinkEnvironment.Config.ProjectFile = Target.ProjectFile; // Add the default resources for dlls if (Config.Type == UEBuildBinaryType.DynamicLinkLibrary) { // Check if there's already a custom resource file if (!BinaryLinkEnvironment.InputFiles.Any(x => x.Reference.HasExtension(".res"))) { if (UEBuildConfiguration.bFormalBuild) { // For formal builds, compile the default resource file per-binary, so that it gets the correct ORIGINAL_FILE_NAME macro. CPPEnvironment BinaryResourceCompileEnvironment = BinaryCompileEnvironment.DeepCopy(); BinaryResourceCompileEnvironment.Config.OutputDirectory = DirectoryReference.Combine(BinaryResourceCompileEnvironment.Config.OutputDirectory, Modules.First().Name); FileItem DefaultResourceFile = FileItem.GetItemByFileReference(FileReference.Combine(UnrealBuildTool.EngineSourceDirectory, "Runtime", "Launch", "Resources", "Windows", "PCLaunch.rc")); CPPOutput DefaultResourceOutput = ToolChain.CompileRCFiles(BinaryResourceCompileEnvironment, new List <FileItem> { DefaultResourceFile }, ActionGraph); BinaryLinkEnvironment.InputFiles.AddRange(DefaultResourceOutput.ObjectFiles); } else { // For non-formal builds, we just want to share the default resource file between modules BinaryLinkEnvironment.InputFiles.AddRange(BinaryLinkEnvironment.DefaultResourceFiles); } } // Add all the common resource files BinaryLinkEnvironment.InputFiles.AddRange(BinaryLinkEnvironment.CommonResourceFiles); } return(BinaryLinkEnvironment); }
/// <summary> /// Creates a compile environment from a base environment based on the module settings. /// </summary> /// <param name="BaseCompileEnvironment">An existing environment to base the module compile environment on.</param> /// <returns>The new module compile environment.</returns> public CPPEnvironment CreateModuleCompileEnvironment(UEBuildTarget Target, CPPEnvironment BaseCompileEnvironment) { CPPEnvironment Result = BaseCompileEnvironment.DeepCopy(); if (Binary == null) { // Adding this check here as otherwise the call to Binary.Config.IntermediateDirectory will give an // unhandled exception throw new BuildException("UEBuildBinary not set up for module {0}", this.ToString()); } // Override compile environment Result.Config.bFasterWithoutUnity = Rules.bFasterWithoutUnity; Result.Config.OptimizeCode = Rules.OptimizeCode; Result.Config.bUseRTTI = Rules.bUseRTTI; Result.Config.bUseAVX = Rules.bUseAVX; Result.Config.bEnableBufferSecurityChecks = Rules.bEnableBufferSecurityChecks; Result.Config.MinSourceFilesForUnityBuildOverride = Rules.MinSourceFilesForUnityBuildOverride; Result.Config.MinFilesUsingPrecompiledHeaderOverride = Rules.MinFilesUsingPrecompiledHeaderOverride; Result.Config.bBuildLocallyWithSNDBS = Rules.bBuildLocallyWithSNDBS; Result.Config.bEnableExceptions = Rules.bEnableExceptions; Result.Config.bEnableShadowVariableWarning = Rules.bEnableShadowVariableWarnings; Result.Config.bUseStaticCRT = (Target.Rules != null && Target.Rules.bUseStaticCRT); Result.Config.OutputDirectory = DirectoryReference.Combine(Binary.Config.IntermediateDirectory, Name); // Switch the optimization flag if we're building a game module. Also pass the definition for building in DebugGame along (see ModuleManager.h for notes). if (Target.Configuration == UnrealTargetConfiguration.DebugGame) { if (!ModuleDirectory.IsUnderDirectory(UnrealBuildTool.EngineDirectory)) { Result.Config.Target.Configuration = CPPTargetConfiguration.Debug; Result.Config.Definitions.Add("UE_BUILD_DEVELOPMENT_WITH_DEBUGGAME=1"); } } // Add the module's private definitions. Result.Config.Definitions.AddRange(Definitions); // Setup the compile environment for the module. SetupPrivateCompileEnvironment(Result.Config.CPPIncludeInfo.IncludePaths, Result.Config.CPPIncludeInfo.SystemIncludePaths, Result.Config.Definitions, Result.Config.AdditionalFrameworks); // @hack to skip adding definitions to compile environment, they will be baked into source code files if (bSkipDefinitionsForCompileEnvironment) { Result.Config.Definitions.Clear(); Result.Config.CPPIncludeInfo.IncludePaths = new HashSet<string>(BaseCompileEnvironment.Config.CPPIncludeInfo.IncludePaths); } return Result; }
/// <summary> /// Creates a compile environment from a base environment based on the module settings. /// </summary> /// <param name="BaseCompileEnvironment">An existing environment to base the module compile environment on.</param> /// <returns>The new module compile environment.</returns> public CPPEnvironment CreateModuleCompileEnvironment(CPPEnvironment BaseCompileEnvironment) { var Result = BaseCompileEnvironment.DeepCopy(); // Override compile environment Result.Config.bFasterWithoutUnity = bFasterWithoutUnity; Result.Config.OptimizeCode = OptimizeCode; Result.Config.bUseRTTI = bUseRTTI; Result.Config.bEnableBufferSecurityChecks = bEnableBufferSecurityChecks; Result.Config.bFasterWithoutUnity = bFasterWithoutUnity; Result.Config.MinFilesUsingPrecompiledHeaderOverride = MinFilesUsingPrecompiledHeaderOverride; Result.Config.bEnableExceptions = bEnableExceptions; Result.Config.bUseStaticCRT = (Target.Rules != null && Target.Rules.bUseStaticCRT); Result.Config.OutputDirectory = Path.Combine(Binary.Config.IntermediateDirectory, Name); // Switch the optimization flag if we're building a game module. Also pass the definition for building in DebugGame along (see ModuleManager.h for notes). if (Target.Configuration == UnrealTargetConfiguration.DebugGame) { PluginInfo Plugin = Plugins.GetPluginInfoForModule(Name); if((Plugin != null && Plugin.LoadedFrom == PluginInfo.LoadedFromType.GameProject) || Type == UEBuildModuleType.Game) { Result.Config.Target.Configuration = CPPTargetConfiguration.Debug; Result.Config.Definitions.Add("UE_BUILD_DEVELOPMENT_WITH_DEBUGGAME=1"); } } // Add the module's private definitions. Result.Config.Definitions.AddRange(Definitions); // Setup the compile environment for the module. SetupPrivateCompileEnvironment(ref Result.Config.CPPIncludeInfo.IncludePaths, ref Result.Config.CPPIncludeInfo.SystemIncludePaths, ref Result.Config.Definitions, ref Result.Config.AdditionalFrameworks); // @hack to skip adding definitions to compile environment, they will be baked into source code files if (bSkipDefinitionsForCompileEnvironment) { Result.Config.Definitions.Clear(); Result.Config.CPPIncludeInfo.IncludePaths = new HashSet<string>(BaseCompileEnvironment.Config.CPPIncludeInfo.IncludePaths); } return Result; }