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); }