static void AppendLibArguments(LinkEnvironment LinkEnvironment, StringBuilder Arguments) { // Prevents the linker from displaying its logo for each invocation. Arguments.Append(" /NOLOGO"); // Prompt the user before reporting internal errors to Microsoft. Arguments.Append(" /errorReport:prompt"); // // PC // // Set machine type/ architecture to be 64 bit. Arguments.Append(" /MACHINE:x64"); if (LinkEnvironment.Config.bIsBuildingConsoleApplication) { Arguments.Append(" /SUBSYSTEM:CONSOLE"); } else { Arguments.Append(" /SUBSYSTEM:WINDOWS"); } // // Shipping & LTCG // if (LinkEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Shipping) { // Use link-time code generation. Arguments.Append(" /LTCG"); } }
/// <summary> /// Called to allow the binary to modify the link environment of a different binary containing /// a module that depends on a module in this binary. /// </summary> /// <param name="DependentLinkEnvironment">The link environment of the dependency</param> public void SetupDependentLinkEnvironment(LinkEnvironment DependentLinkEnvironment) { // Cache the list of libraries in the dependent link environment between calls. We typically run this code path many times for each module. if (DependentLinkLibraries == null) { DependentLinkLibraries = new List <string>(); foreach (FileReference OutputFilePath in OutputFilePaths) { FileReference LibraryFileName; if (Type == UEBuildBinaryType.StaticLibrary || DependentLinkEnvironment.Platform == UnrealTargetPlatform.Mac || DependentLinkEnvironment.Platform == UnrealTargetPlatform.Linux || DependentLinkEnvironment.Platform == UnrealTargetPlatform.LinuxAArch64) { LibraryFileName = OutputFilePath; } else { LibraryFileName = FileReference.Combine(IntermediateDirectory, OutputFilePath.GetFileNameWithoutExtension() + ".lib"); } DependentLinkLibraries.Add(LibraryFileName.FullName); } } DependentLinkEnvironment.AdditionalLibraries.AddRange(DependentLinkLibraries); }
/// <summary> /// Sets up the environment for linking this module. /// </summary> public virtual void SetupPrivateLinkEnvironment( UEBuildBinary SourceBinary, LinkEnvironment LinkEnvironment, List <UEBuildBinary> BinaryDependencies, HashSet <UEBuildModule> VisitedModules, DirectoryReference ExeDir ) { // Add the private rpaths LinkEnvironment.RuntimeLibraryPaths.AddRange(ExpandPathVariables(Rules.PrivateRuntimeLibraryPaths, SourceBinary.OutputDir, ExeDir)); // Allow the module's public dependencies to add library paths and additional libraries to the link environment. SetupPublicLinkEnvironment(SourceBinary, LinkEnvironment.LibraryPaths, LinkEnvironment.AdditionalLibraries, LinkEnvironment.RuntimeLibraryPaths, LinkEnvironment.Frameworks, LinkEnvironment.WeakFrameworks, LinkEnvironment.AdditionalFrameworks, LinkEnvironment.AdditionalShadowFiles, LinkEnvironment.AdditionalBundleResources, LinkEnvironment.DelayLoadDLLs, BinaryDependencies, VisitedModules, ExeDir); // Also allow the module's public and private dependencies to modify the link environment. List <UEBuildModule> AllDependencyModules = new List <UEBuildModule>(); AllDependencyModules.AddRange(PrivateDependencyModules); AllDependencyModules.AddRange(PublicDependencyModules); foreach (UEBuildModule DependencyModule in AllDependencyModules) { DependencyModule.SetupPublicLinkEnvironment(SourceBinary, LinkEnvironment.LibraryPaths, LinkEnvironment.AdditionalLibraries, LinkEnvironment.RuntimeLibraryPaths, LinkEnvironment.Frameworks, LinkEnvironment.WeakFrameworks, LinkEnvironment.AdditionalFrameworks, LinkEnvironment.AdditionalShadowFiles, LinkEnvironment.AdditionalBundleResources, LinkEnvironment.DelayLoadDLLs, BinaryDependencies, VisitedModules, ExeDir); } }
private List <FileItem> CreateOutputFilesForUCA(LinkEnvironment BinaryLinkEnvironment) { var OutputFiles = new List <FileItem>(); var ModuleName = ModuleNames.First(Name => Name.CompareTo(BuildConfiguration.UCAModuleToAnalyze) == 0); var ModuleCPP = (UEBuildModuleCPP)Target.GetModuleByName(ModuleName); var ModulePrivatePCH = ModuleCPP.ProcessedDependencies.UniquePCHHeaderFile; var IntermediatePath = Path.Combine(Target.ProjectIntermediateDirectory, ModuleName); var OutputFileName = Target.OutputPath; var OutputFile = FileItem.GetItemByPath(OutputFileName); Action LinkAction = new Action(ActionType.Compile); LinkAction.WorkingDirectory = Path.GetFullPath("."); LinkAction.CommandPath = System.IO.Path.Combine(LinkAction.WorkingDirectory, @"..", @"Binaries", @"Win32", @"NotForLicensees", @"UnrealCodeAnalyzer.exe"); LinkAction.ProducedItems.Add(OutputFile); LinkAction.PrerequisiteItems.AddRange(BinaryLinkEnvironment.InputFiles); LinkAction.CommandArguments = @"-AnalyzePCHFile -PCHFile=""" + ModulePrivatePCH.AbsolutePath + @""" -OutputFile=""" + OutputFileName + @""" -HeaderDataPath=""" + IntermediatePath + @""" -UsageThreshold " + BuildConfiguration.UCAUsageThreshold.ToString(CultureInfo.InvariantCulture); foreach (string IncludeSearchPath in ModuleCPP.IncludeSearchPaths) { LinkAction.CommandArguments += @" /I""" + LinkAction.WorkingDirectory + @"\" + IncludeSearchPath + @""""; } OutputFiles.Add(OutputFile); return(OutputFiles); }
/// <summary> /// Called to allow the binary to modify the link environment of a different binary containing /// a module that depends on a module in this binary. /// </summary> /// <param name="DependentLinkEnvironment">The link environment of the dependency</param> public override void SetupDependentLinkEnvironment(LinkEnvironment DependentLinkEnvironment) { // Cache the list of libraries in the dependent link environment between calls. We typically run this code path many times for each module. if (DependentLinkLibraries == null) { DependentLinkLibraries = new List <string>(); foreach (FileReference OutputFilePath in Config.OutputFilePaths) { FileReference LibraryFileName; if (Config.Type == UEBuildBinaryType.StaticLibrary || DependentLinkEnvironment.Config.Platform == CPPTargetPlatform.Mac || DependentLinkEnvironment.Config.Platform == CPPTargetPlatform.Linux) { LibraryFileName = OutputFilePath; } else { LibraryFileName = FileReference.Combine(Config.IntermediateDirectory, OutputFilePath.GetFileNameWithoutExtension() + ".lib"); } DependentLinkLibraries.Add(LibraryFileName.FullName); } } DependentLinkEnvironment.Config.AdditionalLibraries.AddRange(DependentLinkLibraries); // If we're linking against static library containing the launch module on windows, we need to add the compiled resource separately. We can't link it through the static library. if (Config.Type == UEBuildBinaryType.StaticLibrary && Modules.Any(x => x.Name == "Launch") && (Target.Platform == UnrealTargetPlatform.Win32 || Target.Platform == UnrealTargetPlatform.Win64)) { FileReference ResourceFileRef = FileReference.Combine(Config.IntermediateDirectory, "Launch", "PCLaunch.rc.res"); DependentLinkEnvironment.InputFiles.Add(FileItem.GetItemByFileReference(ResourceFileRef)); } }
static string GetLibArguments(LinkEnvironment LinkEnvironment) { string Result = ""; // Prevents the linker from displaying its logo for each invocation. Result += " /NOLOGO"; // Prompt the user before reporting internal errors to Microsoft. Result += " /errorReport:prompt"; // Set machine type/ architecture to be 64 bit. Result += " /MACHINE:x64"; Result += " /SUBSYSTEM:WINDOWS"; // // Shipping & LTCG // if (LinkEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Shipping) { // Use link-time code generation. Result += " /ltcg"; } return(Result); }
/// <summary> /// Builds the binary. /// </summary> /// <param name="Target">Rules for the target being built</param> /// <param name="ToolChain">The toolchain which to use for building</param> /// <param name="CompileEnvironment">The environment to compile the binary in</param> /// <param name="LinkEnvironment">The environment to link the binary in</param> /// <param name="SharedPCHs">List of templates for shared PCHs</param> /// <param name="WorkingSet">The working set of source files</param> /// <param name="ActionGraph">Graph to add build actions to</param> /// <returns>Set of built products</returns> public IEnumerable <FileItem> Build(ReadOnlyTargetRules Target, UEToolChain ToolChain, CppCompileEnvironment CompileEnvironment, LinkEnvironment LinkEnvironment, List <PrecompiledHeaderTemplate> SharedPCHs, ISourceFileWorkingSet WorkingSet, ActionGraph ActionGraph) { // Return nothing if we're using precompiled binaries if (bUsePrecompiled) { return(new List <FileItem>()); } // Setup linking environment. LinkEnvironment BinaryLinkEnvironment = SetupBinaryLinkEnvironment(Target, ToolChain, LinkEnvironment, CompileEnvironment, SharedPCHs, WorkingSet, ActionGraph); // If we're generating projects, we only need include paths and definitions, there is no need to run the linking logic. if (ProjectFileGenerator.bGenerateProjectFiles) { return(BinaryLinkEnvironment.InputFiles); } // If linking is disabled, our build products are just the compiled object files if (Target.bDisableLinking) { return(BinaryLinkEnvironment.InputFiles); } // Return linked files. return(SetupOutputFiles(ToolChain, CompileEnvironment, BinaryLinkEnvironment, ActionGraph)); }
/** Copy constructor. */ public LinkEnvironment(LinkEnvironment InCopyEnvironment) { InputFiles.AddRange(InCopyEnvironment.InputFiles); InputLibraries.AddRange(InCopyEnvironment.InputLibraries); Config = new LinkEnvironmentConfiguration(InCopyEnvironment.Config); }
static string GetLibArguments(LinkEnvironment LinkEnvironment) { string Result = ""; if (LinkEnvironment.Architecture == "-win32") // simulator { // Prevents the linker from displaying its logo for each invocation. Result += " /NOLOGO"; // Prompt the user before reporting internal errors to Microsoft. Result += " /errorReport:prompt"; // Win32 build Result += " /MACHINE:x86"; // Always CONSOLE because of main() Result += " /SUBSYSTEM:CONSOLE"; // // Shipping & LTCG // if (LinkEnvironment.Configuration == CppConfiguration.Shipping) { // Use link-time code generation. Result += " /ltcg"; } return(Result); } return(Result); }
/// <summary> /// Copy constructor. /// </summary> protected LinkEnvironment(LinkEnvironment InCopyEnvironment) { InputFiles.AddRange(InCopyEnvironment.InputFiles); InputLibraries.AddRange(InCopyEnvironment.InputLibraries); Config = new LinkEnvironmentConfiguration(InCopyEnvironment.Config); }
/// <summary> /// Sets up the environment for linking this module. /// </summary> public virtual void SetupPrivateLinkEnvironment( UEBuildBinary SourceBinary, LinkEnvironment LinkEnvironment, List <UEBuildBinary> BinaryDependencies, HashSet <UEBuildModule> VisitedModules, DirectoryReference ExeDir ) { // Add the private rpaths LinkEnvironment.RuntimeLibraryPaths.AddRange(ExpandPathVariables(Rules.PrivateRuntimeLibraryPaths, SourceBinary.OutputDir, ExeDir)); // Allow the module's public dependencies to add library paths and additional libraries to the link environment. SetupPublicLinkEnvironment(SourceBinary, LinkEnvironment.LibraryPaths, LinkEnvironment.AdditionalLibraries, LinkEnvironment.RuntimeLibraryPaths, LinkEnvironment.Frameworks, LinkEnvironment.WeakFrameworks, LinkEnvironment.AdditionalFrameworks, LinkEnvironment.AdditionalBundleResources, LinkEnvironment.DelayLoadDLLs, BinaryDependencies, VisitedModules, ExeDir); // Also allow the module's public and private dependencies to modify the link environment. List <UEBuildModule> AllDependencyModules = new List <UEBuildModule>(); AllDependencyModules.AddRange(PrivateDependencyModules); AllDependencyModules.AddRange(PublicDependencyModules); foreach (UEBuildModule DependencyModule in AllDependencyModules) { DependencyModule.SetupPublicLinkEnvironment(SourceBinary, LinkEnvironment.LibraryPaths, LinkEnvironment.AdditionalLibraries, LinkEnvironment.RuntimeLibraryPaths, LinkEnvironment.Frameworks, LinkEnvironment.WeakFrameworks, LinkEnvironment.AdditionalFrameworks, LinkEnvironment.AdditionalBundleResources, LinkEnvironment.DelayLoadDLLs, BinaryDependencies, VisitedModules, ExeDir); } // Add all the additional properties LinkEnvironment.AdditionalProperties.AddRange(Rules.AdditionalPropertiesForReceipt.Inner); // this is a link-time property that needs to be accumulated (if any modules contributing to this module is ignoring, all are ignoring) LinkEnvironment.bIgnoreUnresolvedSymbols |= Rules.bIgnoreUnresolvedSymbols; }
/// <summary> /// Called to allow the binary to modify the link environment of a different binary containing /// a module that depends on a module in this binary. /// </summary> /// <param name="DependentLinkEnvironment">The link environment of the dependency</param> public override void SetupDependentLinkEnvironment(LinkEnvironment DependentLinkEnvironment) { foreach (string OutputFilePath in Config.OutputFilePaths) { string LibraryFileName; if (Config.Type == UEBuildBinaryType.StaticLibrary || DependentLinkEnvironment.Config.Target.Platform == CPPTargetPlatform.Mac || DependentLinkEnvironment.Config.Target.Platform == CPPTargetPlatform.Linux) { LibraryFileName = OutputFilePath; } else { LibraryFileName = Path.Combine(Config.IntermediateDirectory, Path.GetFileNameWithoutExtension(OutputFilePath) + ".lib"); } DependentLinkEnvironment.Config.AdditionalLibraries.Add(LibraryFileName); } // If we're linking against static library containing the launch module on windows, we need to add the compiled resource separately. We can't link it through the static library. if (Config.Type == UEBuildBinaryType.StaticLibrary && ModuleNames.Contains("Launch") && (Target.Platform == UnrealTargetPlatform.Win32 || Target.Platform == UnrealTargetPlatform.Win64)) { string ResourceFilePath = Path.Combine(Config.IntermediateDirectory, "Launch", "PCLaunch.rc.res"); DependentLinkEnvironment.InputFiles.Add(FileItem.GetItemByPath(ResourceFilePath)); } }
static string GetLinkArguments(LinkEnvironment LinkEnvironment, string Architecture) { string Result = ""; Result += " -nostdlib"; Result += " -Wl,-shared,-Bsymbolic"; Result += " -Wl,--no-undefined"; if (Architecture == "-armv7") { Result += ToolchainParamsArm; Result += " -march=armv7-a"; Result += " -Wl,--fix-cortex-a8"; // required to route around a CPU bug in some Cortex-A8 implementations } else if (Architecture == "-x86") { Result += ToolchainParamsx86; Result += " -march=atom"; } // verbose output from the linker // Result += " -v"; return(Result); }
public override FileItem LinkFiles(LinkEnvironment LinkEnvironment, bool bBuildImportLibraryOnly, IActionGraphBuilder Graph) { FileItem OutputFile = FileItem.GetItemByFileReference(LinkEnvironment.OutputFilePath); Action LinkAction = Graph.CreateAction(ActionType.Link); LinkAction.CommandDescription = "FakeCompile"; LinkAction.CommandPath = BuildHostPlatform.Current.Shell; if (BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Win64) { LinkAction.CommandArguments = String.Format("/C echo Linked > {0}", LinkEnvironment.OutputFilePath.FullName); } else { LinkAction.CommandArguments = String.Format("echo Linked > {0}", Utils.EscapeShellArgument(LinkEnvironment.OutputFilePath.FullName)); } LinkAction.WorkingDirectory = UnrealBuildTool.EngineSourceDirectory; foreach (FileItem InputFile in LinkEnvironment.InputFiles) { LinkAction.PrerequisiteItems.Add(InputFile); } LinkAction.ProducedItems.Add(OutputFile); LinkAction.DeleteItems.Add(OutputFile); LinkAction.StatusDescription = OutputFile.Location.GetFileName(); LinkAction.bCanExecuteRemotely = false; return(OutputFile); }
static string GetArArguments(LinkEnvironment LinkEnvironment) { string Result = ""; Result += " -r"; return Result; }
/** Creates an action to archive all the .o files into single .a file */ public FileItem CreateArchiveAndIndex(LinkEnvironment LinkEnvironment) { // Create an archive action Action ArchiveAction = new Action(ActionType.Link); ArchiveAction.WorkingDirectory = Path.GetFullPath("."); bool bUsingSh = BuildHostPlatform.Current.Platform != UnrealTargetPlatform.Win64 && BuildHostPlatform.Current.Platform != UnrealTargetPlatform.Win32; if (bUsingSh) { ArchiveAction.CommandPath = "/bin/sh"; ArchiveAction.CommandArguments = "-c '"; } else { ArchiveAction.CommandPath = "cmd.exe"; ArchiveAction.CommandArguments = "/c "; } // this will produce a final library ArchiveAction.bProducesImportLibrary = true; // Add the output file as a production of the link action. FileItem OutputFile = FileItem.GetItemByPath(LinkEnvironment.Config.OutputFilePath); ArchiveAction.ProducedItems.Add(OutputFile); ArchiveAction.CommandDescription = "Archive"; ArchiveAction.StatusDescription = Path.GetFileName(OutputFile.AbsolutePath); ArchiveAction.CommandArguments += string.Format("{0} {1} \"{2}\"", GetArPath(LinkEnvironment.Config.Target.Architecture), GetArchiveArguments(LinkEnvironment), OutputFile.AbsolutePath); // Add the input files to a response file, and pass the response file on the command-line. List <string> InputFileNames = new List <string>(); foreach (FileItem InputFile in LinkEnvironment.InputFiles) { string InputAbsolutePath = InputFile.AbsolutePath.Replace("\\", "/"); InputFileNames.Add(string.Format("\"{0}\"", InputAbsolutePath)); ArchiveAction.PrerequisiteItems.Add(InputFile); ArchiveAction.CommandArguments += string.Format(" \"{0}\"", InputAbsolutePath); } // add ranlib ArchiveAction.CommandArguments += string.Format(" && {0} \"{1}\"", GetRanlibPath(LinkEnvironment.Config.Target.Architecture), OutputFile.AbsolutePath); // Add the additional arguments specified by the environment. ArchiveAction.CommandArguments += LinkEnvironment.Config.AdditionalArguments; ArchiveAction.CommandArguments.Replace("\\", "/"); if (bUsingSh) { ArchiveAction.CommandArguments += "'"; } // Only execute linking on the local PC. ArchiveAction.bCanExecuteRemotely = false; return(OutputFile); }
static string GetLinkArguments(LinkEnvironment LinkEnvironment) { string Result = GetSharedArguments_Global(LinkEnvironment.Config.Target.Configuration, LinkEnvironment.Config.Target.Architecture, false); if (LinkEnvironment.Config.Target.Architecture != "-win32") // ! simulator { // suppress link time warnings Result += " -Wno-ignored-attributes"; // function alias that always gets resolved Result += " -Wno-parentheses"; // precedence order Result += " -Wno-shift-count-overflow"; // 64bit is more than enough for shift 32 // enable verbose mode Result += " -v"; if (LinkEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Debug || LinkEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Development) { // check for alignment/etc checking // Result += " -s SAFE_HEAP=1"; //Result += " -s CHECK_HEAP_ALIGN=1"; //Result += " -s SAFE_DYNCALLS=1"; // enable assertions in non-Shipping/Release builds Result += " -s ASSERTIONS=1"; } if (LinkEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Debug) { Result += " -O0"; } else // development & shipping { Result += " -s ASM_JS=1"; if (UEBuildConfiguration.bCompileForSize) { Result += " -Oz -s OUTLINING_LIMIT=40000"; } else { Result += " -s OUTLINING_LIMIT=110000"; if (LinkEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Development) { Result += " -O2"; } if (LinkEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Shipping) { Result += " -O3"; } } } Result += " -s CASE_INSENSITIVE_FS=1"; // Result += " -s EVAL_CTORS=1"; } return(Result); }
/// <summary> /// Copy constructor. /// </summary> public LinkEnvironment(LinkEnvironment Other) { Platform = Other.Platform; Configuration = Other.Configuration; Architecture = Other.Architecture; BundleDirectory = Other.BundleDirectory; OutputDirectory = Other.OutputDirectory; IntermediateDirectory = Other.IntermediateDirectory; LocalShadowDirectory = Other.LocalShadowDirectory; OutputFilePaths = Other.OutputFilePaths.ToList(); LibraryPaths.AddRange(Other.LibraryPaths); ExcludedLibraries.AddRange(Other.ExcludedLibraries); AdditionalLibraries.AddRange(Other.AdditionalLibraries); RuntimeLibraryPaths.AddRange(Other.RuntimeLibraryPaths); Frameworks.AddRange(Other.Frameworks); AdditionalFrameworks.AddRange(Other.AdditionalFrameworks); WeakFrameworks.AddRange(Other.WeakFrameworks); AdditionalBundleResources.AddRange(Other.AdditionalBundleResources); DelayLoadDLLs.AddRange(Other.DelayLoadDLLs); AdditionalArguments = Other.AdditionalArguments; bCreateDebugInfo = Other.bCreateDebugInfo; bGenerateRuntimeSymbolFiles = Other.bGenerateRuntimeSymbolFiles; bIsBuildingLibrary = Other.bIsBuildingLibrary; bDisableSymbolCache = Other.bDisableSymbolCache; bIsBuildingDLL = Other.bIsBuildingDLL; bIsBuildingConsoleApplication = Other.bIsBuildingConsoleApplication; WindowsEntryPointOverride = Other.WindowsEntryPointOverride; bIsCrossReferenced = Other.bIsCrossReferenced; bHasExports = Other.bHasExports; bIsBuildingDotNetAssembly = Other.bIsBuildingDotNetAssembly; DefaultStackSize = Other.DefaultStackSize; DefaultStackSizeCommit = Other.DefaultStackSizeCommit; bOptimizeForSize = Other.bOptimizeForSize; bOmitFramePointers = Other.bOmitFramePointers; bSupportEditAndContinue = Other.bSupportEditAndContinue; bUseIncrementalLinking = Other.bUseIncrementalLinking; bAllowLTCG = Other.bAllowLTCG; bPGOOptimize = Other.bPGOOptimize; bPGOProfile = Other.bPGOProfile; PGODirectory = Other.PGODirectory; PGOFilenamePrefix = Other.PGOFilenamePrefix; bCreateMapFile = Other.bCreateMapFile; bAllowASLR = Other.bAllowASLR; bUsePDBFiles = Other.bUsePDBFiles; bUseFastPDBLinking = Other.bUseFastPDBLinking; bIgnoreUnresolvedSymbols = Other.bIgnoreUnresolvedSymbols; bPrintTimingInfo = Other.bPrintTimingInfo; BundleVersion = Other.BundleVersion; InstallName = Other.InstallName; InputFiles.AddRange(Other.InputFiles); DefaultResourceFiles.AddRange(Other.DefaultResourceFiles); CommonResourceFiles.AddRange(Other.CommonResourceFiles); IncludeFunctions.AddRange(Other.IncludeFunctions); ModuleDefinitionFile = Other.ModuleDefinitionFile; AdditionalProperties.AddRange(Other.AdditionalProperties); }
/// <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(UEBuildTarget Target, UEToolChain ToolChain, CPPEnvironment CompileEnvironment, LinkEnvironment LinkEnvironment, List <PrecompiledHeaderTemplate> SharedPCHs, ActionGraph ActionGraph) { // UnrealCodeAnalyzer produces output files only for a specific module. if (BuildConfiguration.bRunUnrealCodeAnalyzer && !(Modules.Any(x => x.Name == BuildConfiguration.UCAModuleToAnalyze))) { return(new List <FileItem>()); } // Setup linking environment. LinkEnvironment BinaryLinkEnvironment = SetupBinaryLinkEnvironment(Target, ToolChain, LinkEnvironment, CompileEnvironment, SharedPCHs, ActionGraph); // Return linked files. return(SetupOutputFiles(ToolChain, ref BinaryLinkEnvironment, ActionGraph)); }
public FileItem FixDependencies(LinkEnvironment LinkEnvironment, FileItem Executable) { if (!LinkEnvironment.Config.bIsCrossReferenced) { return(null); } Log.TraceVerbose("Adding postlink step"); bool bUseCmdExe = BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Win64 || BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Win32; string ShellBinary = bUseCmdExe ? "cmd.exe" : "/bin/sh"; string ExecuteSwitch = bUseCmdExe ? " /C" : ""; // avoid -c so scripts don't need +x string ScriptName = bUseCmdExe ? "FixDependencies.bat" : "FixDependencies.sh"; FileItem FixDepsScript = FileItem.GetItemByFullPath(Path.Combine(LinkEnvironment.Config.LocalShadowDirectory, ScriptName)); Action PostLinkAction = new Action(ActionType.Link); PostLinkAction.WorkingDirectory = Path.GetFullPath("."); PostLinkAction.CommandPath = ShellBinary; PostLinkAction.StatusDescription = string.Format("{0}", Path.GetFileName(Executable.AbsolutePath)); PostLinkAction.CommandDescription = "FixDeps"; PostLinkAction.bCanExecuteRemotely = false; PostLinkAction.CommandArguments = ExecuteSwitch; PostLinkAction.CommandArguments += bUseCmdExe ? " \"" : " -c '"; FileItem OutputFile = FileItem.GetItemByPath(Path.Combine(LinkEnvironment.Config.LocalShadowDirectory, Path.GetFileNameWithoutExtension(Executable.AbsolutePath) + ".link")); // Make sure we don't run this script until the all executables and shared libraries // have been built. PostLinkAction.PrerequisiteItems.Add(Executable); foreach (FileItem Dependency in BundleDependencies) { PostLinkAction.PrerequisiteItems.Add(Dependency); } PostLinkAction.CommandArguments += ShellBinary + ExecuteSwitch + " \"" + FixDepsScript.AbsolutePath + "\" && "; string Touch = bUseCmdExe ? "echo \"\" >> \"{0}\" && copy /b \"{0}\" +,," : "touch \"{0}\""; PostLinkAction.CommandArguments += String.Format(Touch, OutputFile.AbsolutePath); PostLinkAction.CommandArguments += bUseCmdExe ? "\"" : "'"; System.Console.WriteLine("{0} {1}", PostLinkAction.CommandPath, PostLinkAction.CommandArguments); PostLinkAction.ProducedItems.Add(OutputFile); return(OutputFile); }
static string GetLinkArguments(LinkEnvironment LinkEnvironment) { string Result = ""; // debugging symbols if (LinkEnvironment.Config.Target.Configuration < CPPTargetConfiguration.Shipping) { Result += " -rdynamic"; // needed for backtrace_symbols()... } else { Result += " -s"; // Strip binaries in Shipping } if (LinkEnvironment.Config.bIsBuildingDLL) { Result += " -shared"; } else { // ignore unresolved symbols in shared libs Result += string.Format(" -Wl,--unresolved-symbols=ignore-in-shared-libs"); } if (UnrealBuildTool.BuildingRocket()) { // strip symbols for Rocket in every configuration Result += " -Wl,-s"; } // RPATH for third party libs Result += " -Wl,-rpath=${ORIGIN}"; Result += " -Wl,-rpath-link=${ORIGIN}"; Result += " -Wl,-rpath=${ORIGIN}/../../../Engine/Binaries/Linux"; Result += " -Wl,-rpath=${ORIGIN}/.."; // for modules that are in sub-folders of the main Engine/Binary/Linux folder // FIXME: really ugly temp solution. Modules need to be able to specify this Result += " -Wl,-rpath=${ORIGIN}/../../../Engine/Binaries/ThirdParty/ICU/icu4c-53_1/Linux/x86_64-unknown-linux-gnu"; if (CrossCompiling()) { if (UsingClang()) { Result += String.Format(" -target {0}", LinkEnvironment.Config.Target.Architecture); // Set target triple } string SysRootPath = BaseLinuxPath.TrimEnd(new char[] { '\\', '/' }); Result += String.Format(" \"--sysroot={0}\"", SysRootPath); } return(Result); }
static string GetLinkArguments(LinkEnvironment LinkEnvironment) { string Result = GetSharedArguments_Global(LinkEnvironment.Config.Target.Configuration, LinkEnvironment.Config.Target.Architecture); if (LinkEnvironment.Config.Target.Architecture != "-win32") { // enable verbose mode Result += " -v"; if (LinkEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Debug) { // check for alignment/etc checking //Result += " -s SAFE_HEAP=1"; //Result += " -s CHECK_HEAP_ALIGN=1"; //Result += " -s SAFE_DYNCALLS=1"; // enable assertions in non-Shipping/Release builds Result += " -s ASSERTIONS=1"; } if (LinkEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Debug) { Result += " -O0"; } if (LinkEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Debug || LinkEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Development) { Result += " -s GL_ASSERTIONS=1 "; } if (LinkEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Development) { Result += " -O2 -s ASM_JS=1 -s OUTLINING_LIMIT=110000 -g2 "; } if (LinkEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Shipping) { Result += " -O3 -s ASM_JS=1 -s OUTLINING_LIMIT=40000"; } Result += " -s CASE_INSENSITIVE_FS=1 "; string BaseSDKPath = Environment.GetEnvironmentVariable("EMSCRIPTEN"); Result += " --js-library \"" + BaseSDKPath + "/Src/library_openal.js\" "; } return(Result); }
private List <FileItem> SetupOutputFiles(UEToolChain ToolChain, CppCompileEnvironment BinaryCompileEnvironment, LinkEnvironment BinaryLinkEnvironment, ActionGraph ActionGraph) { // // Regular linking action. // List <FileItem> OutputFiles = new List <FileItem>(); if (bCreateImportLibrarySeparately) { // Mark the link environment as cross-referenced. BinaryLinkEnvironment.bIsCrossReferenced = true; if (BinaryLinkEnvironment.Platform != CppPlatform.Mac && BinaryLinkEnvironment.Platform != CppPlatform.Linux) { // Create the import library. OutputFiles.AddRange(ToolChain.LinkAllFiles(BinaryLinkEnvironment, true, ActionGraph)); } } BinaryLinkEnvironment.bIncludeDependentLibrariesInLibrary = bIncludeDependentLibrariesInLibrary; // Link the binary. FileItem[] Executables = ToolChain.LinkAllFiles(BinaryLinkEnvironment, false, ActionGraph); OutputFiles.AddRange(Executables); // Produce additional console app if requested if (Config.bBuildAdditionalConsoleApp) { // Produce additional binary but link it as a console app LinkEnvironment ConsoleAppLinkEvironment = new LinkEnvironment(BinaryLinkEnvironment); ConsoleAppLinkEvironment.bIsBuildingConsoleApplication = true; ConsoleAppLinkEvironment.WindowsEntryPointOverride = "WinMainCRTStartup"; // For WinMain() instead of "main()" for Launch module ConsoleAppLinkEvironment.OutputFilePaths = ConsoleAppLinkEvironment.OutputFilePaths.Select(Path => GetAdditionalConsoleAppPath(Path)).ToList(); // Link the console app executable OutputFiles.AddRange(ToolChain.LinkAllFiles(ConsoleAppLinkEvironment, false, ActionGraph)); } foreach (FileItem Executable in Executables) { OutputFiles.AddRange(ToolChain.PostBuild(Executable, BinaryLinkEnvironment, ActionGraph)); } return(OutputFiles); }
/// <summary> /// Copy constructor. /// </summary> public LinkEnvironment(LinkEnvironment Other) { Platform = Other.Platform; Configuration = Other.Configuration; Architecture = Other.Architecture; OutputDirectory = Other.OutputDirectory; IntermediateDirectory = Other.IntermediateDirectory; LocalShadowDirectory = Other.LocalShadowDirectory; OutputFilePaths = Other.OutputFilePaths.ToList(); ProjectFile = Other.ProjectFile; LibraryPaths.AddRange(Other.LibraryPaths); ExcludedLibraries.AddRange(Other.ExcludedLibraries); AdditionalLibraries.AddRange(Other.AdditionalLibraries); Frameworks.AddRange(Other.Frameworks); AdditionalShadowFiles.AddRange(Other.AdditionalShadowFiles); AdditionalFrameworks.AddRange(Other.AdditionalFrameworks); WeakFrameworks.AddRange(Other.WeakFrameworks); AdditionalBundleResources.AddRange(Other.AdditionalBundleResources); DelayLoadDLLs.AddRange(Other.DelayLoadDLLs); AdditionalArguments = Other.AdditionalArguments; bCreateDebugInfo = Other.bCreateDebugInfo; bIsBuildingLibrary = Other.bIsBuildingLibrary; bDisableSymbolCache = Other.bDisableSymbolCache; bIsBuildingDLL = Other.bIsBuildingDLL; bIsBuildingConsoleApplication = Other.bIsBuildingConsoleApplication; WindowsEntryPointOverride = Other.WindowsEntryPointOverride; bIsCrossReferenced = Other.bIsCrossReferenced; bHasExports = Other.bHasExports; bIsBuildingDotNetAssembly = Other.bIsBuildingDotNetAssembly; bOptimizeForSize = Other.bOptimizeForSize; bOmitFramePointers = Other.bOmitFramePointers; bSupportEditAndContinue = Other.bSupportEditAndContinue; bUseIncrementalLinking = Other.bUseIncrementalLinking; bAllowLTCG = Other.bAllowLTCG; bCreateMapFile = Other.bCreateMapFile; bAllowALSR = Other.bAllowALSR; bUsePDBFiles = Other.bUsePDBFiles; bUseFastPDBLinking = Other.bUseFastPDBLinking; bPrintTimingInfo = Other.bPrintTimingInfo; BundleVersion = Other.BundleVersion; InputFiles.AddRange(Other.InputFiles); InputLibraries.AddRange(Other.InputLibraries); DefaultResourceFiles.AddRange(Other.DefaultResourceFiles); CommonResourceFiles.AddRange(Other.CommonResourceFiles); }
public override ICollection <FileItem> PostBuild(FileItem Executable, LinkEnvironment BinaryLinkEnvironment) { var OutputFiles = base.PostBuild(Executable, BinaryLinkEnvironment); if (BinaryLinkEnvironment.Config.bIsBuildingDLL || BinaryLinkEnvironment.Config.bIsBuildingLibrary) { return(OutputFiles); } FileItem FixDepsOutputFile = FixDependencies(BinaryLinkEnvironment, Executable); if (FixDepsOutputFile != null) { OutputFiles.Add(FixDepsOutputFile); } return(OutputFiles); }
/// <summary> /// Called to allow the binary to modify the link environment of a different binary containing /// a module that depends on a module in this binary. /// </summary> /// <param name="DependentLinkEnvironment">The link environment of the dependency</param> public override void SetupDependentLinkEnvironment(ref LinkEnvironment DependentLinkEnvironment) { foreach (string OutputFilePath in Config.OutputFilePaths) { string LibraryFileName; if (Config.Type == UEBuildBinaryType.StaticLibrary || DependentLinkEnvironment.Config.Target.Platform == CPPTargetPlatform.Mac || DependentLinkEnvironment.Config.Target.Platform == CPPTargetPlatform.Linux) { LibraryFileName = OutputFilePath; } else { LibraryFileName = Path.Combine(Config.IntermediateDirectory, Path.GetFileNameWithoutExtension(OutputFilePath) + ".lib"); } DependentLinkEnvironment.Config.AdditionalLibraries.Add(LibraryFileName); } }
/** Allows the game to add any additional environment settings before building */ public void SetUpGameEnvironment(CPPEnvironment GameCPPEnvironment, LinkEnvironment FinalLinkEnvironment, List<UE3ProjectDesc> GameProjects) { GameCPPEnvironment.IncludePaths.Add("ExampleGame/Inc"); GameProjects.Add( new UE3ProjectDesc( "ExampleGame/ExampleGame.vcproj") ); if (UE3BuildConfiguration.bBuildEditor && (GameCPPEnvironment.TargetPlatform == CPPTargetPlatform.Win32 || GameCPPEnvironment.TargetPlatform == CPPTargetPlatform.Win64)) { GameProjects.Add( new UE3ProjectDesc( "ExampleEditor/ExampleEditor.vcproj") ); GameCPPEnvironment.IncludePaths.Add("ExampleEditor/Inc"); } GameCPPEnvironment.Definitions.Add("GAMENAME=EXAMPLEGAME"); GameCPPEnvironment.Definitions.Add("IS_EXAMPLEGAME=1"); FinalLinkEnvironment.AdditionalLibraries.Add("ws2_32.lib"); FinalLinkEnvironment.AdditionalLibraries.Add("../../Binaries/win32/Network.lib"); }
public static void AddAppBundleContentsToManifest(ref FileManifest Manifest, UEBuildBinary Binary) { if (Binary.Target.GlobalLinkEnvironment.Config.bIsBuildingConsoleApplication || Binary.Config.Type != UEBuildBinaryType.Executable) { return; } string ContentsDirectory = Path.GetDirectoryName(Path.GetDirectoryName(Binary.Config.OutputFilePath)) + "/"; // We need to know what third party dylibs would be copied to the bundle var Modules = Binary.GetAllDependencyModules(bIncludeDynamicallyLoaded: false, bForceCircular: false); var BinaryLinkEnvironment = new LinkEnvironment(Binary.Target.GlobalLinkEnvironment); var BinaryDependencies = new List<UEBuildBinary>(); var LinkEnvironmentVisitedModules = new Dictionary<UEBuildModule, bool>(); foreach (var Module in Modules) { Module.SetupPrivateLinkEnvironment(ref BinaryLinkEnvironment, ref BinaryDependencies, ref LinkEnvironmentVisitedModules); } foreach (string AdditionalLibrary in BinaryLinkEnvironment.Config.AdditionalLibraries) { string LibName = Path.GetFileName(AdditionalLibrary); if (LibName.StartsWith("lib")) { if (Path.GetExtension(AdditionalLibrary) == ".dylib") { Manifest.AddFileName(ContentsDirectory + "MacOS/" + LibName); } } } // And we also need all the resources Manifest.AddFileName(ContentsDirectory + "Info.plist"); Manifest.AddFileName(ContentsDirectory + "PkgInfo"); Manifest.AddFileName(ContentsDirectory + "Resources/UE4.icns"); Manifest.AddFileName(ContentsDirectory + "Resources/OpenXcodeAtFileAndLine.applescript"); Manifest.AddFileName(ContentsDirectory + "Resources/English.lproj/InfoPlist.strings"); Manifest.AddFileName(ContentsDirectory + "Resources/English.lproj/MainMenu.nib"); Manifest.AddFileName(ContentsDirectory + "Resources/RadioEffectUnit.component/Contents/MacOS/RadioEffectUnit"); Manifest.AddFileName(ContentsDirectory + "Resources/RadioEffectUnit.component/Contents/Resources/English.lproj/Localizable.strings"); Manifest.AddFileName(ContentsDirectory + "Resources/RadioEffectUnit.component/Contents/Resources/RadioEffectUnit.rsrc"); Manifest.AddFileName(ContentsDirectory + "Resources/RadioEffectUnit.component/Contents/Info.plist"); }
string GetLinkArguments(LinkEnvironment LinkEnvironment, string Architecture) { string Result = ""; Result += " -nostdlib"; Result += " -Wl,-shared,-Bsymbolic"; Result += " -Wl,--no-undefined"; if (Architecture == "-arm64") { Result += ToolchainParamsArm64; Result += " -march=armv8-a"; } else if (Architecture == "-x86") { Result += ToolchainParamsx86; Result += " -march=atom"; } else if (Architecture == "-x64") { Result += ToolchainParamsx64; Result += " -march=atom"; } else // if (Architecture == "-armv7") { Result += ToolchainParamsArm; Result += " -march=armv7-a"; Result += " -Wl,--fix-cortex-a8"; // required to route around a CPU bug in some Cortex-A8 implementations } if (BuildConfiguration.bUseUnityBuild && ClangVersionFloat >= 3.6f && ClangVersionFloat < 3.8f) { Result += " -fuse-ld=gold"; // ld.gold is available in r10e (clang 3.6) } // make sure the DT_SONAME field is set properly (or we can a warning toast at startup on new Android) Result += " -Wl,-soname,libUE4.so"; // verbose output from the linker // Result += " -v"; return Result; }
protected override string GetLinkArguments(LinkEnvironment LinkEnvironment, string Architecture) { string Result = ""; if (LinkEnvironment.bIsBuildingDLL) { Result += " -Wl,-shared,-Bsymbolic"; } else { // ignore unresolved symbols in shared libs Result += string.Format(" -Wl,--unresolved-symbols=ignore-in-shared-libs"); } Result += " -Wl,-z,nocopyreloc"; Result += " -Wl,--warn-shared-textrel"; Result += " -Wl,--fatal-warnings"; Result += " -Wl,--no-undefined"; Result += " -no-canonical-prefixes"; Result += " -Wl,-z,relro"; Result += " -Wl,-z,now"; Result += " -Wl,--enable-new-dtags"; Result += " -Wl,--export-dynamic"; Result += " -Wl,-rpath=$ORIGIN"; Result += " -fdiagnostics-format=msvc"; if (!LinkEnvironment.bCreateDebugInfo) { Result += " -Wl,--strip-debug"; } if (!LinkEnvironment.bIsBuildingDLL) { // Position independent code executable *only*. Result += " -pie"; } Result += ToolchainParamsArm64; return(Result); }
/// <summary> /// Get the name of the response file for the current linker environment and output file /// </summary> /// <param name="LinkEnvironment"></param> /// <param name="OutputFile"></param> /// <returns></returns> public static string GetResponseFileName( LinkEnvironment LinkEnvironment, FileItem OutputFile ) { // Construct a relative path for the intermediate response file string ResponseFileName = Path.Combine( LinkEnvironment.Config.IntermediateDirectory, Path.GetFileName( OutputFile.AbsolutePath ) + ".response" ); if (UnrealBuildTool.HasUProjectFile()) { // If this is the uproject being built, redirect the intermediate if (Utils.IsFileUnderDirectory( OutputFile.AbsolutePath, UnrealBuildTool.GetUProjectPath() )) { ResponseFileName = Path.Combine( UnrealBuildTool.GetUProjectPath(), BuildConfiguration.PlatformIntermediateFolder, Path.GetFileNameWithoutExtension(UnrealBuildTool.GetUProjectFile()), LinkEnvironment.Config.TargetConfiguration.ToString(), Path.GetFileName(OutputFile.AbsolutePath) + ".response"); } } // Convert the relative path to an absolute path ResponseFileName = Path.GetFullPath( ResponseFileName ); return ResponseFileName; }
/// <summary> /// Sets up the environment for linking this module. /// </summary> public virtual void SetupPrivateLinkEnvironment( UEBuildBinary SourceBinary, LinkEnvironment LinkEnvironment, List <UEBuildBinary> BinaryDependencies, HashSet <UEBuildModule> 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 <UEBuildModule> AllDependencyModules = new List <UEBuildModule>(); 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); } }
/// <summary> /// Get the name of the response file for the current linker environment and output file /// </summary> /// <param name="LinkEnvironment"></param> /// <param name="OutputFile"></param> /// <returns></returns> public static string GetResponseFileName(LinkEnvironment LinkEnvironment, FileItem OutputFile) { // Construct a relative path for the intermediate response file string ResponseFileName = Path.Combine(LinkEnvironment.Config.IntermediateDirectory, Path.GetFileName(OutputFile.AbsolutePath) + ".response"); if (UnrealBuildTool.HasUProjectFile()) { // If this is the uproject being built, redirect the intermediate if (Utils.IsFileUnderDirectory(OutputFile.AbsolutePath, UnrealBuildTool.GetUProjectPath())) { ResponseFileName = Path.Combine( UnrealBuildTool.GetUProjectPath(), BuildConfiguration.PlatformIntermediateFolder, Path.GetFileNameWithoutExtension(UnrealBuildTool.GetUProjectFile()), LinkEnvironment.Config.Target.Configuration.ToString(), Path.GetFileName(OutputFile.AbsolutePath) + ".response"); } } // Convert the relative path to an absolute path ResponseFileName = Path.GetFullPath(ResponseFileName); return(ResponseFileName); }
public override ICollection<FileItem> PostBuild(FileItem Executable, LinkEnvironment BinaryLinkEnvironment) { var OutputFiles = base.PostBuild(Executable, BinaryLinkEnvironment); if (BinaryLinkEnvironment.Config.bIsBuildingLibrary) { return OutputFiles; } foreach (UEBuildBundleResource Resource in BinaryLinkEnvironment.Config.AdditionalBundleResources) { OutputFiles.Add(CopyBundleResource(Resource, Executable)); } // If building for Mac on a Mac, use actions to finalize the builds (otherwise, we use Deploy) if (BuildHostPlatform.Current.Platform != UnrealTargetPlatform.Mac) { return OutputFiles; } if (BinaryLinkEnvironment.Config.bIsBuildingDLL || BinaryLinkEnvironment.Config.bIsBuildingLibrary) { return OutputFiles; } FileItem FixDylibOutputFile = FixDylibDependencies(BinaryLinkEnvironment, Executable); OutputFiles.Add(FixDylibOutputFile); if (!BinaryLinkEnvironment.Config.bIsBuildingConsoleApplication) { OutputFiles.Add(FinalizeAppBundle(BinaryLinkEnvironment, Executable, FixDylibOutputFile)); } return OutputFiles; }
public override FileItem LinkFiles(LinkEnvironment LinkEnvironment, bool bBuildImportLibraryOnly) { if (LinkEnvironment.Config.Target.Architecture == "-win32") // simulator { return base.LinkFiles(LinkEnvironment, bBuildImportLibraryOnly); } FileItem OutputFile; // Make the final javascript file Action LinkAction = new Action(ActionType.Link); // ResponseFile lines. List<string> ReponseLines = new List<string>(); LinkAction.bCanExecuteRemotely = false; LinkAction.WorkingDirectory = UnrealBuildTool.EngineSourceDirectory.FullName; LinkAction.CommandPath = HTML5SDKInfo.Python(); LinkAction.CommandArguments = HTML5SDKInfo.EmscriptenCompiler(); ReponseLines.Add(GetLinkArguments(LinkEnvironment)); // Add the input files to a response file, and pass the response file on the command-line. foreach (FileItem InputFile in LinkEnvironment.InputFiles) { //System.Console.WriteLine("File {0} ", InputFile.AbsolutePath); ReponseLines.Add(string.Format(" \"{0}\"", InputFile.AbsolutePath)); LinkAction.PrerequisiteItems.Add(InputFile); } if (!LinkEnvironment.Config.bIsBuildingLibrary) { // Make sure ThirdParty libs are at the end. List<string> ThirdParty = (from Lib in LinkEnvironment.Config.AdditionalLibraries where Lib.Contains("ThirdParty") select Lib).ToList(); LinkEnvironment.Config.AdditionalLibraries.RemoveAll(Element => Element.Contains("ThirdParty")); LinkEnvironment.Config.AdditionalLibraries.AddRange(ThirdParty); foreach (string InputFile in LinkEnvironment.Config.AdditionalLibraries) { FileItem Item = FileItem.GetItemByPath(InputFile); if (Item.AbsolutePath.Contains(".lib")) continue; if (Item != null) { if (Item.ToString().Contains(".js")) ReponseLines.Add(string.Format(" --js-library \"{0}\"", Item.AbsolutePath)); else ReponseLines.Add(string.Format(" \"{0}\"", Item.AbsolutePath)); LinkAction.PrerequisiteItems.Add(Item); } } } // make the file we will create OutputFile = FileItem.GetItemByFileReference(LinkEnvironment.Config.OutputFilePath); LinkAction.ProducedItems.Add(OutputFile); ReponseLines.Add(string.Format(" -o \"{0}\"", OutputFile.AbsolutePath)); FileItem OutputBC = FileItem.GetItemByPath(LinkEnvironment.Config.OutputFilePath.FullName.Replace(".js", ".bc").Replace(".html", ".bc")); LinkAction.ProducedItems.Add(OutputBC); ReponseLines.Add(" --emit-symbol-map " + string.Format(" --save-bc \"{0}\"", OutputBC.AbsolutePath)); LinkAction.StatusDescription = Path.GetFileName(OutputFile.AbsolutePath); FileReference ResponseFileName = GetResponseFileName(LinkEnvironment, OutputFile); LinkAction.CommandArguments += string.Format(" @\"{0}\"", ResponseFile.Create(ResponseFileName, ReponseLines)); LinkAction.OutputEventHandler = new DataReceivedEventHandler(RemoteOutputReceivedEventHandler); return OutputFile; }
static string GetLibArguments(LinkEnvironment LinkEnvironment) { string Result = ""; if (LinkEnvironment.Config.Target.Architecture == "-win32") // simulator { // Prevents the linker from displaying its logo for each invocation. Result += " /NOLOGO"; // Prompt the user before reporting internal errors to Microsoft. Result += " /errorReport:prompt"; // Win32 build Result += " /MACHINE:x86"; // Always CONSOLE because of main() Result += " /SUBSYSTEM:CONSOLE"; // // Shipping & LTCG // if (LinkEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Shipping) { // Use link-time code generation. Result += " /ltcg"; } return Result; } return Result; }
static string GetLinkArguments(LinkEnvironment LinkEnvironment) { string Result = GetSharedArguments_Global(LinkEnvironment.Config.Target.Configuration, LinkEnvironment.Config.Target.Architecture, false); if (LinkEnvironment.Config.Target.Architecture != "-win32") // ! simulator { // suppress link time warnings Result += " -Wno-ignored-attributes"; // function alias that always gets resolved Result += " -Wno-parentheses"; // precedence order Result += " -Wno-shift-count-overflow"; // 64bit is more than enough for shift 32 // enable verbose mode Result += " -v"; if (LinkEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Debug || LinkEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Development) { // check for alignment/etc checking // Result += " -s SAFE_HEAP=1"; //Result += " -s CHECK_HEAP_ALIGN=1"; //Result += " -s SAFE_DYNCALLS=1"; // enable assertions in non-Shipping/Release builds Result += " -s ASSERTIONS=1"; } if (LinkEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Debug) { Result += " -O0"; } else // development & shipping { Result += " -s ASM_JS=1"; if (UEBuildConfiguration.bCompileForSize) { Result += " -Oz -s OUTLINING_LIMIT=40000"; } else { Result += " -s OUTLINING_LIMIT=110000"; if (LinkEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Development) { Result += " -O2"; } if (LinkEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Shipping) { Result += " -O3"; } } } Result += " -s CASE_INSENSITIVE_FS=1"; } return Result; }
public virtual ICollection<FileItem> PostBuild(FileItem Executable, LinkEnvironment ExecutableLinkEnvironment) { return new List<FileItem>(); }
/// <summary> /// Get the name of the response file for the current linker environment and output file /// </summary> /// <param name="LinkEnvironment"></param> /// <param name="OutputFile"></param> /// <returns></returns> public static FileReference GetResponseFileName(LinkEnvironment LinkEnvironment, FileItem OutputFile) { // Construct a relative path for the intermediate response file return FileReference.Combine(LinkEnvironment.Config.IntermediateDirectory, OutputFile.Reference.GetFileName() + ".response"); }
public virtual FileItem[] LinkAllFiles(LinkEnvironment LinkEnvironment, bool bBuildImportLibraryOnly) { return new FileItem[] { LinkFiles(LinkEnvironment, bBuildImportLibraryOnly) }; }
public override FileItem LinkFiles(LinkEnvironment LinkEnvironment, bool bBuildImportLibraryOnly) { if (LinkEnvironment.Config.Target.Architecture == "-win32") { return base.LinkFiles(LinkEnvironment, bBuildImportLibraryOnly); } FileItem OutputFile; // Make the final javascript file Action LinkAction = new Action(ActionType.Link); LinkAction.bCanExecuteRemotely = false; LinkAction.WorkingDirectory = Path.GetFullPath("."); LinkAction.CommandPath = PythonPath; LinkAction.CommandArguments = EMCCPath; LinkAction.CommandArguments += GetLinkArguments(LinkEnvironment); // Add the input files to a response file, and pass the response file on the command-line. foreach (FileItem InputFile in LinkEnvironment.InputFiles) { System.Console.WriteLine("File {0} ", InputFile.AbsolutePath); LinkAction.CommandArguments += string.Format(" \"{0}\"", InputFile.AbsolutePath); LinkAction.PrerequisiteItems.Add(InputFile); } foreach (string InputFile in LinkEnvironment.Config.AdditionalLibraries) { FileItem Item = FileItem.GetItemByPath(InputFile); if (Item.AbsolutePath.Contains(".lib")) continue; if (Item != null) { if (Item.ToString().Contains(".js")) LinkAction.CommandArguments += string.Format(" --js-library \"{0}\"", Item.AbsolutePath); else LinkAction.CommandArguments += string.Format(" \"{0}\"", Item.AbsolutePath); LinkAction.PrerequisiteItems.Add(Item); } } // make the file we will create OutputFile = FileItem.GetItemByPath(LinkEnvironment.Config.OutputFilePath); LinkAction.ProducedItems.Add(OutputFile); LinkAction.CommandArguments += string.Format(" -o \"{0}\"", OutputFile.AbsolutePath); FileItem OutputBC = FileItem.GetItemByPath(LinkEnvironment.Config.OutputFilePath.Replace(".js", ".bc").Replace(".html", ".bc")); LinkAction.ProducedItems.Add(OutputBC); LinkAction.CommandArguments += string.Format(" --save-bc \"{0}\"", OutputBC.AbsolutePath); LinkAction.StatusDescription = Path.GetFileName(OutputFile.AbsolutePath); LinkAction.OutputEventHandler = new DataReceivedEventHandler(RemoteOutputReceivedEventHandler); return OutputFile; }
FileItem FixDylibDependencies(LinkEnvironment LinkEnvironment, FileItem Executable) { Action LinkAction = new Action(ActionType.Link); LinkAction.WorkingDirectory = Path.GetFullPath("."); LinkAction.CommandPath = "/bin/sh"; LinkAction.CommandDescription = ""; // Call the FixDylibDependencies.sh script which will link the dylibs and the main executable, this time proper ones, as it's called // once all are already created, so the cross dependency problem no longer prevents linking. // The script is deleted after it's executed so it's empty when we start appending link commands for the next executable. FileItem FixDylibDepsScript = FileItem.GetItemByFullPath(Path.Combine(LinkEnvironment.Config.LocalShadowDirectory, "FixDylibDependencies.sh")); FileItem RemoteFixDylibDepsScript = LocalToRemoteFileItem(FixDylibDepsScript, true); LinkAction.CommandArguments = "-c 'chmod +x \"" + RemoteFixDylibDepsScript.AbsolutePath + "\"; \"" + RemoteFixDylibDepsScript.AbsolutePath + "\"; if [[ $? -ne 0 ]]; then exit 1; fi; "; if (BuildHostPlatform.Current.Platform != UnrealTargetPlatform.Mac) { LinkAction.ActionHandler = new Action.BlockingActionHandler(RPCUtilHelper.RPCActionHandler); } // Make sure this action is executed after all the dylibs and the main executable are created foreach (FileItem Dependency in BundleDependencies) { LinkAction.PrerequisiteItems.Add(Dependency); } BundleDependencies.Clear(); LinkAction.StatusDescription = string.Format("Fixing dylib dependencies for {0}", Path.GetFileName(Executable.AbsolutePath)); LinkAction.bCanExecuteRemotely = false; FileItem OutputFile = FileItem.GetItemByPath(Path.Combine(LinkEnvironment.Config.LocalShadowDirectory, Path.GetFileNameWithoutExtension(Executable.AbsolutePath) + ".link")); FileItem RemoteOutputFile = LocalToRemoteFileItem(OutputFile, false); LinkAction.CommandArguments += "echo \"Dummy\" >> \"" + RemoteOutputFile.AbsolutePath + "\""; LinkAction.CommandArguments += "'"; LinkAction.ProducedItems.Add(RemoteOutputFile); return RemoteOutputFile; }
static string GetLinkArguments(LinkEnvironment LinkEnvironment, string Architecture) { string Result = ""; Result += " -nostdlib"; Result += " -Wl,-shared,-Bsymbolic"; Result += " -Wl,--no-undefined"; if (Architecture == "-arm64") { Result += ToolchainParamsArm64; Result += " -march=armv8-a"; } else if (Architecture == "-x86") { Result += ToolchainParamsx86; Result += " -march=atom"; } else if (Architecture == "-x64") { Result += ToolchainParamsx64; Result += " -march=atom"; } else // if (Architecture == "-armv7") { Result += ToolchainParamsArm; Result += " -march=armv7-a"; Result += " -Wl,--fix-cortex-a8"; // required to route around a CPU bug in some Cortex-A8 implementations } if (BuildConfiguration.bUseUnityBuild && ClangVersionFloat >= 3.6f) { Result += " -fuse-ld=gold"; // ld.gold is available in r10e (clang 3.6) } // verbose output from the linker // Result += " -v"; return Result; }
static string GetLinkArguments(LinkEnvironment LinkEnvironment) { string Result = ""; // Prevents the linker from displaying its logo for each invocation. Result += " /NOLOGO"; Result += " /TLBID:1"; // Don't create a side-by-side manifest file for the executable. Result += " /MANIFEST:NO"; if (LinkEnvironment.Config.bCreateDebugInfo) { // Output debug info for the linked executable. Result += " /DEBUG"; } // Prompt the user before reporting internal errors to Microsoft. Result += " /errorReport:prompt"; // Set machine type/ architecture to be 64 bit. Result += " /MACHINE:x64"; Result += " /DYNAMICBASE \"d2d1.lib\" \"d3d11.lib\" \"dxgi.lib\" \"ole32.lib\" \"windowscodecs.lib\" \"dwrite.lib\" \"kernel32.lib\""; // WinRT // if (WinRTPlatform.ShouldCompileWinRT() == true) { // generate metadata // Result += " /WINMD:ONLY"; Result += " /WINMD"; Result += " /APPCONTAINER"; // location of metadata Result += string.Format(" /WINMDFILE:\"{0}\"", Path.ChangeExtension(LinkEnvironment.Config.OutputFilePath, "winmd")); } if (LinkEnvironment.Config.Target.Platform == CPPTargetPlatform.WinRT_ARM) { // Link for console. Result += " /SUBSYSTEM:CONSOLE"; } else { // Link for Windows. Result += " /SUBSYSTEM:WINDOWS"; } // Allow the OS to load the EXE at different base addresses than its preferred base address. Result += " /FIXED:No"; // Explicitly declare that the executable is compatible with Data Execution Prevention. Result += " /NXCOMPAT"; // Set the default stack size. Result += " /STACK:5000000,5000000"; // Allow delay-loaded DLLs to be explicitly unloaded. Result += " /DELAY:UNLOAD"; if (LinkEnvironment.Config.bIsBuildingDLL == true) { Result += " /DLL"; } // // ReleaseLTCG // if (BuildConfiguration.bAllowLTCG && LinkEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Shipping) { // Use link-time code generation. Result += " /LTCG"; // This is where we add in the PGO-Lite linkorder.txt if we are using PGO-Lite //Result += " /ORDER:@linkorder.txt"; //Result += " /VERBOSE"; } // // Shipping binary // if (LinkEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Shipping) { // Generate an EXE checksum. Result += " /RELEASE"; // Eliminate unreferenced symbols. Result += " /OPT:REF"; // Remove redundant COMDATs. Result += " /OPT:ICF"; } // // Regular development binary. // else { // Keep symbols that are unreferenced. Result += " /OPT:NOREF"; // Disable identical COMDAT folding. Result += " /OPT:NOICF"; } // Enable incremental linking if wanted. if (BuildConfiguration.bUseIncrementalLinking) { Result += " /INCREMENTAL"; } // Disabled by default as it can cause issues and forces local execution. else { Result += " /INCREMENTAL:NO"; } return Result; }
public override FileItem LinkFiles(LinkEnvironment LinkEnvironment, bool bBuildImportLibraryOnly) { string LinkerPath = XcodeDeveloperDir + "Toolchains/XcodeDefault.xctoolchain/usr/bin/" + (LinkEnvironment.Config.bIsBuildingLibrary ? IOSArchiver : IOSLinker); // Create an action that invokes the linker. Action LinkAction = new Action(ActionType.Link); if (!Utils.IsRunningOnMono && BuildHostPlatform.Current.Platform != UnrealTargetPlatform.Mac) { LinkAction.ActionHandler = new Action.BlockingActionHandler(RPCUtilHelper.RPCActionHandler); } // RPC utility parameters are in terms of the Mac side LinkAction.WorkingDirectory = GetMacDevSrcRoot(); LinkAction.CommandPath = LinkerPath; // build this up over the rest of the function LinkAction.CommandArguments = LinkEnvironment.Config.bIsBuildingLibrary ? GetArchiveArguments_Global(LinkEnvironment) : GetLinkArguments_Global(LinkEnvironment); if (!LinkEnvironment.Config.bIsBuildingLibrary) { // Add the library paths to the argument list. foreach (string LibraryPath in LinkEnvironment.Config.LibraryPaths) { LinkAction.CommandArguments += string.Format(" -L\"{0}\"", LibraryPath); } // Add the additional libraries to the argument list. foreach (string AdditionalLibrary in LinkEnvironment.Config.AdditionalLibraries) { // for absolute library paths, convert to remote filename if (!String.IsNullOrEmpty(Path.GetDirectoryName(AdditionalLibrary))) { // add it to the prerequisites to make sure it's built first (this should be the case of non-system libraries) FileItem LibFile = FileItem.GetItemByPath(Path.GetFullPath(AdditionalLibrary)); FileItem RemoteLibFile = LocalToRemoteFileItem(LibFile, false); LinkAction.PrerequisiteItems.Add(RemoteLibFile); // and add to the commandline LinkAction.CommandArguments += string.Format(" \"{0}\"", ConvertPath(Path.GetFullPath(AdditionalLibrary))); } else { LinkAction.CommandArguments += string.Format(" -l\"{0}\"", AdditionalLibrary); } } } if (BuildHostPlatform.Current.Platform != UnrealTargetPlatform.Mac) { // Add any additional files that we'll need in order to link the app foreach (string AdditionalShadowFile in LinkEnvironment.Config.AdditionalShadowFiles) { FileItem ShadowFile = FileItem.GetExistingItemByPath(AdditionalShadowFile); if (ShadowFile != null) { QueueFileForBatchUpload(ShadowFile); LinkAction.PrerequisiteItems.Add(ShadowFile); } else { throw new BuildException("Couldn't find required additional file to shadow: {0}", AdditionalShadowFile); } } } // Handle additional framework assets that might need to be shadowed foreach ( UEBuildFramework Framework in LinkEnvironment.Config.AdditionalFrameworks ) { if ( Framework.OwningModule == null || Framework.FrameworkZipPath == null || Framework.FrameworkZipPath == "" ) { continue; // Only care about frameworks that have a zip specified } // If we've already remembered this framework, skip if ( RememberedAdditionalFrameworks.Contains( Framework ) ) { continue; } // Remember any files we need to unzip RememberedAdditionalFrameworks.Add( Framework ); // Copy them to remote mac if needed if ( BuildHostPlatform.Current.Platform != UnrealTargetPlatform.Mac ) { FileItem ShadowFile = FileItem.GetExistingItemByPath( GetLocalFrameworkZipPath( Framework ) ); if ( ShadowFile != null ) { QueueFileForBatchUpload( ShadowFile ); LinkAction.PrerequisiteItems.Add( ShadowFile ); } else { throw new BuildException( "Couldn't find required additional file to shadow: {0}", Framework.FrameworkZipPath ); } } } // Add the output file as a production of the link action. FileItem OutputFile = FileItem.GetItemByPath(Path.GetFullPath(LinkEnvironment.Config.OutputFilePath)); FileItem RemoteOutputFile = LocalToRemoteFileItem(OutputFile, false); LinkAction.ProducedItems.Add(RemoteOutputFile); // Add the input files to a response file, and pass the response file on the command-line. List<string> InputFileNames = new List<string>(); foreach (FileItem InputFile in LinkEnvironment.InputFiles) { InputFileNames.Add(string.Format("\"{0}\"", InputFile.AbsolutePath)); LinkAction.PrerequisiteItems.Add(InputFile); } // Write the list of input files to a response file, with a tempfilename, on remote machine if (LinkEnvironment.Config.bIsBuildingLibrary) { foreach (string Filename in InputFileNames) { LinkAction.CommandArguments += " " + Filename; } // @todo rocket lib: the -filelist command should take a response file (see else condition), except that it just says it can't // find the file that's in there. Rocket.lib may overflow the commandline by putting all files on the commandline, so this // may be needed: // LinkAction.CommandArguments += string.Format(" -filelist \"{0}\"", ConvertPath(ResponsePath)); } else { bool bIsUE4Game = LinkEnvironment.Config.OutputFilePath.Contains("UE4Game"); string ResponsePath = Path.GetFullPath(Path.Combine((!bIsUE4Game && !string.IsNullOrEmpty(UnrealBuildTool.GetUProjectPath())) ? UnrealBuildTool.GetUProjectPath() : BuildConfiguration.RelativeEnginePath, BuildConfiguration.PlatformIntermediateFolder, "LinkFileList_" + Path.GetFileNameWithoutExtension(LinkEnvironment.Config.OutputFilePath) + ".tmp")); if (!Utils.IsRunningOnMono && BuildHostPlatform.Current.Platform != UnrealTargetPlatform.Mac) { ResponseFile.Create (ResponsePath, InputFileNames); RPCUtilHelper.CopyFile (ResponsePath, ConvertPath (ResponsePath), true); } else { ResponseFile.Create(ConvertPath(ResponsePath), InputFileNames); } LinkAction.CommandArguments += string.Format(" @\"{0}\"", ConvertPath(ResponsePath)); } // Add the output file to the command-line. LinkAction.CommandArguments += string.Format(" -o \"{0}\"", RemoteOutputFile.AbsolutePath); // Add the additional arguments specified by the environment. LinkAction.CommandArguments += LinkEnvironment.Config.AdditionalArguments; // Only execute linking on the local PC. LinkAction.bCanExecuteRemotely = false; LinkAction.StatusDescription = string.Format("{0}", OutputFile.AbsolutePath); LinkAction.OutputEventHandler = new DataReceivedEventHandler(RemoteOutputReceivedEventHandler); // For iPhone, generate the dSYM file if the config file is set to do so if (BuildConfiguration.bGeneratedSYMFile == true && Path.GetExtension(OutputFile.AbsolutePath) != ".a") { Log.TraceInformation("Generating the dSYM file - this will add some time to your build..."); RemoteOutputFile = GenerateDebugInfo(RemoteOutputFile); } return RemoteOutputFile; }
string GetLinkArguments_Global( LinkEnvironment LinkEnvironment ) { IOSPlatform BuildPlat = UEBuildPlatform.GetBuildPlatform(UnrealTargetPlatform.IOS) as IOSPlatform; BuildPlat.SetUpProjectEnvironment(UnrealTargetPlatform.IOS); string Result = ""; if (LinkEnvironment.Config.Target.Architecture == "-simulator") { Result += " -arch i386"; Result += " -isysroot " + XcodeDeveloperDir + "Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator" + IOSSDKVersion + ".sdk"; } else { Result += Result += GetArchitectureArgument(LinkEnvironment.Config.Target.Configuration, LinkEnvironment.Config.Target.Architecture); Result += " -isysroot " + XcodeDeveloperDir + "Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS" + IOSSDKVersion + ".sdk"; } Result += " -dead_strip"; Result += " -miphoneos-version-min=" + BuildPlat.GetRunTimeVersion(); Result += " -Wl,-no_pie"; // Result += " -v"; // link in the frameworks foreach (string Framework in LinkEnvironment.Config.Frameworks) { Result += " -framework " + Framework; } foreach (UEBuildFramework Framework in LinkEnvironment.Config.AdditionalFrameworks) { if ( Framework.OwningModule != null && Framework.FrameworkZipPath != null && Framework.FrameworkZipPath != "" ) { // If this framework has a zip specified, we'll need to setup the path as well Result += " -F \"" + GetRemoteIntermediateFrameworkZipPath( Framework ) + "\""; } Result += " -framework " + Framework.FrameworkName; } foreach (string Framework in LinkEnvironment.Config.WeakFrameworks) { Result += " -weak_framework " + Framework; } return Result; }
/** Sets up the environment for linking this module. */ public virtual void SetupPrivateLinkEnvironment( UEBuildBinary SourceBinary, LinkEnvironment LinkEnvironment, List<UEBuildBinary> BinaryDependencies, Dictionary<UEBuildModule, bool> VisitedModules ) { // Allow the module's public dependencies to add library paths and additional libraries to the link environment. SetupPublicLinkEnvironment(SourceBinary, LinkEnvironment.Config.LibraryPaths, LinkEnvironment.Config.AdditionalLibraries, LinkEnvironment.Config.Frameworks, LinkEnvironment.Config.WeakFrameworks, LinkEnvironment.Config.AdditionalFrameworks,LinkEnvironment.Config.AdditionalShadowFiles, LinkEnvironment.Config.AdditionalBundleResources, LinkEnvironment.Config.DelayLoadDLLs, BinaryDependencies, VisitedModules); // Also allow the module's public and private dependencies to modify the link environment. List<string> AllDependencyModuleNames = new List<string>(PrivateDependencyModuleNames); AllDependencyModuleNames.AddRange(PublicDependencyModuleNames); foreach (var DependencyName in AllDependencyModuleNames) { var DependencyModule = Target.GetModuleByName(DependencyName); DependencyModule.SetupPublicLinkEnvironment(SourceBinary, LinkEnvironment.Config.LibraryPaths, LinkEnvironment.Config.AdditionalLibraries, LinkEnvironment.Config.Frameworks, LinkEnvironment.Config.WeakFrameworks, LinkEnvironment.Config.AdditionalFrameworks, LinkEnvironment.Config.AdditionalShadowFiles, LinkEnvironment.Config.AdditionalBundleResources, LinkEnvironment.Config.DelayLoadDLLs, BinaryDependencies, VisitedModules); } }
public override void SetupPrivateLinkEnvironment( UEBuildBinary SourceBinary, LinkEnvironment LinkEnvironment, List<UEBuildBinary> BinaryDependencies, Dictionary<UEBuildModule, bool> VisitedModules ) { base.SetupPrivateLinkEnvironment(SourceBinary, LinkEnvironment, BinaryDependencies, VisitedModules); // Setup the link environment for linking a CLR binary. LinkEnvironment.Config.CLRMode = CPPCLRMode.CLREnabled; }
/** * Creates app bundle for a given executable * * @param Executable FileItem describing the executable to generate app bundle for */ FileItem FinalizeAppBundle(LinkEnvironment LinkEnvironment, FileItem Executable, FileItem FixDylibOutputFile) { // Make a file item for the source and destination files string FullDestPath = Executable.AbsolutePath.Substring(0, Executable.AbsolutePath.IndexOf(".app") + 4); FileItem DestFile = FileItem.GetItemByPath(FullDestPath); FileItem RemoteDestFile = LocalToRemoteFileItem(DestFile, false); // Make the compile action Action FinalizeAppBundleAction = new Action(ActionType.CreateAppBundle); FinalizeAppBundleAction.WorkingDirectory = Path.GetFullPath("."); FinalizeAppBundleAction.CommandPath = "/bin/sh"; FinalizeAppBundleAction.CommandDescription = ""; // make path to the script FileItem BundleScript = FileItem.GetItemByFullPath(Path.Combine(LinkEnvironment.Config.IntermediateDirectory, "FinalizeAppBundle.sh")); FileItem RemoteBundleScript = LocalToRemoteFileItem(BundleScript, true); if (BuildHostPlatform.Current.Platform != UnrealTargetPlatform.Mac) { FinalizeAppBundleAction.ActionHandler = new Action.BlockingActionHandler(RPCUtilHelper.RPCActionHandler); } FinalizeAppBundleAction.CommandArguments = "\"" + RemoteBundleScript.AbsolutePath + "\""; FinalizeAppBundleAction.PrerequisiteItems.Add(FixDylibOutputFile); FinalizeAppBundleAction.ProducedItems.Add(RemoteDestFile); FinalizeAppBundleAction.StatusDescription = string.Format("Finalizing app bundle: {0}.app", Path.GetFileName(Executable.AbsolutePath)); FinalizeAppBundleAction.bCanExecuteRemotely = false; return RemoteDestFile; }
static string GetArchiveArguments_Global(LinkEnvironment LinkEnvironment) { string Result = ""; Result += " -static"; return Result; }
string GetLinkArguments_Global(LinkEnvironment LinkEnvironment) { string Result = ""; Result += " -arch x86_64"; Result += " -isysroot " + BaseSDKDir + "/MacOSX" + MacOSSDKVersion + ".sdk"; Result += " -mmacosx-version-min=" + MacOSVersion; Result += " -dead_strip"; if (LinkEnvironment.Config.bIsBuildingDLL) { Result += " -dynamiclib"; } // Needed to make sure install_name_tool will be able to update paths in Mach-O headers Result += " -headerpad_max_install_names"; Result += " -lc++"; return Result; }
public override FileItem LinkFiles(LinkEnvironment LinkEnvironment, bool bBuildImportLibraryOnly) { return null; }
public override FileItem LinkFiles(LinkEnvironment LinkEnvironment, bool bBuildImportLibraryOnly) { bool bIsBuildingLibrary = LinkEnvironment.Config.bIsBuildingLibrary || bBuildImportLibraryOnly; // Create an action that invokes the linker. Action LinkAction = new Action(ActionType.Link); if (BuildHostPlatform.Current.Platform != UnrealTargetPlatform.Mac) { LinkAction.ActionHandler = new Action.BlockingActionHandler(RPCUtilHelper.RPCActionHandler); } LinkAction.WorkingDirectory = GetMacDevSrcRoot(); LinkAction.CommandPath = "/bin/sh"; LinkAction.CommandDescription = "Link"; string EngineAPIVersion = LoadEngineAPIVersion(); string EngineDisplayVersion = LoadEngineDisplayVersion(true); string VersionArg = LinkEnvironment.Config.bIsBuildingDLL ? " -current_version " + EngineAPIVersion + " -compatibility_version " + EngineDisplayVersion : ""; string Linker = bIsBuildingLibrary ? MacArchiver : MacLinker; string LinkCommand = ToolchainDir + Linker + VersionArg + " " + (bIsBuildingLibrary ? GetArchiveArguments_Global(LinkEnvironment) : GetLinkArguments_Global(LinkEnvironment)); // Tell the action that we're building an import library here and it should conditionally be // ignored as a prerequisite for other actions LinkAction.bProducesImportLibrary = !Utils.IsRunningOnMono && (bBuildImportLibraryOnly || LinkEnvironment.Config.bIsBuildingDLL); // Add the output file as a production of the link action. FileItem OutputFile = FileItem.GetItemByPath(Path.GetFullPath(LinkEnvironment.Config.OutputFilePath)); OutputFile.bNeedsHotReloadNumbersDLLCleanUp = LinkEnvironment.Config.bIsBuildingDLL; FileItem RemoteOutputFile = LocalToRemoteFileItem(OutputFile, false); // To solve the problem with cross dependencies, for now we create a broken dylib that does not link with other engine dylibs. // This is fixed in later step, FixDylibDependencies. For this and to know what libraries to copy whilst creating an app bundle, // we gather the list of engine dylibs. List<string> EngineAndGameLibraries = new List<string>(); string DylibsPath = "@rpath"; string AbsolutePath = OutputFile.AbsolutePath.Replace("\\", "/"); if (!bIsBuildingLibrary) { LinkCommand += " -rpath @loader_path/ -rpath @executable_path/"; } List<string> ThirdPartyLibraries = new List<string>(); if (BuildHostPlatform.Current.Platform != UnrealTargetPlatform.Mac) { // Add any additional files that we'll need in order to link the app foreach (string AdditionalShadowFile in LinkEnvironment.Config.AdditionalShadowFiles) { FileItem ShadowFile = FileItem.GetExistingItemByPath(AdditionalShadowFile); if (ShadowFile != null) { QueueFileForBatchUpload(ShadowFile); LinkAction.PrerequisiteItems.Add(ShadowFile); } else { throw new BuildException("Couldn't find required additional file to shadow: {0}", AdditionalShadowFile); } } // Add any frameworks to be shadowed to the remote foreach (string FrameworkPath in LinkEnvironment.Config.Frameworks) { if(FrameworkPath.EndsWith(".framework")) { foreach(string FrameworkFile in Directory.EnumerateFiles(FrameworkPath, "*", SearchOption.AllDirectories)) { FileItem FrameworkFileItem = FileItem.GetExistingItemByPath(FrameworkFile); QueueFileForBatchUpload(FrameworkFileItem); LinkAction.PrerequisiteItems.Add(FrameworkFileItem); } } } } bool bIsBuildingAppBundle = !LinkEnvironment.Config.bIsBuildingDLL && !LinkEnvironment.Config.bIsBuildingLibrary && !LinkEnvironment.Config.bIsBuildingConsoleApplication; List<string> RPaths = new List<string>(); if (!bIsBuildingLibrary || LinkEnvironment.Config.bIncludeDependentLibrariesInLibrary) { // Add the additional libraries to the argument list. foreach (string AdditionalLibrary in LinkEnvironment.Config.AdditionalLibraries) { // Can't link dynamic libraries when creating a static one if (bIsBuildingLibrary && (Path.GetExtension(AdditionalLibrary) == ".dylib" || AdditionalLibrary == "z")) { continue; } if (Path.GetFileName(AdditionalLibrary).StartsWith("lib")) { LinkCommand += string.Format(" \"{0}\"", ConvertPath(Path.GetFullPath(AdditionalLibrary))); if (Path.GetExtension(AdditionalLibrary) == ".dylib") { ThirdPartyLibraries.Add(AdditionalLibrary); } if (BuildHostPlatform.Current.Platform != UnrealTargetPlatform.Mac) { // copy over libs we may need FileItem ShadowFile = FileItem.GetExistingItemByPath(AdditionalLibrary); if (ShadowFile != null) { QueueFileForBatchUpload(ShadowFile); } } } else if (Path.GetDirectoryName(AdditionalLibrary) != "" && (Path.GetDirectoryName(AdditionalLibrary).Contains("Binaries/Mac") || Path.GetDirectoryName(AdditionalLibrary).Contains("Binaries\\Mac"))) { // It's an engine or game dylib. Save it for later EngineAndGameLibraries.Add(ConvertPath(Path.GetFullPath(AdditionalLibrary))); if (!Utils.IsRunningOnMono) { FileItem EngineLibDependency = FileItem.GetItemByPath(Path.GetFullPath(AdditionalLibrary)); LinkAction.PrerequisiteItems.Add(EngineLibDependency); FileItem RemoteEngineLibDependency = FileItem.GetRemoteItemByPath(ConvertPath(Path.GetFullPath(AdditionalLibrary)), UnrealTargetPlatform.Mac); LinkAction.PrerequisiteItems.Add(RemoteEngineLibDependency); //Log.TraceInformation("Adding {0} / {1} as a prereq to {2}", EngineLibDependency.AbsolutePath, RemoteEngineLibDependency.AbsolutePath, RemoteOutputFile.AbsolutePath); } else if (LinkEnvironment.Config.bIsCrossReferenced == false) { FileItem EngineLibDependency = FileItem.GetItemByPath(Path.GetFullPath(AdditionalLibrary)); LinkAction.PrerequisiteItems.Add(EngineLibDependency); } } else if (AdditionalLibrary.Contains(".framework/")) { LinkCommand += string.Format(" \'{0}\'", AdditionalLibrary); } else { LinkCommand += string.Format(" -l{0}", AdditionalLibrary); } AddLibraryPathToRPaths(AdditionalLibrary, AbsolutePath, ref RPaths, ref LinkCommand, bIsBuildingAppBundle); } foreach (string AdditionalLibrary in LinkEnvironment.Config.DelayLoadDLLs) { // Can't link dynamic libraries when creating a static one if (bIsBuildingLibrary && (Path.GetExtension(AdditionalLibrary) == ".dylib" || AdditionalLibrary == "z")) { continue; } LinkCommand += string.Format(" -weak_library \"{0}\"", ConvertPath(Path.GetFullPath(AdditionalLibrary))); AddLibraryPathToRPaths(AdditionalLibrary, AbsolutePath, ref RPaths, ref LinkCommand, bIsBuildingAppBundle); } } // Add frameworks Dictionary<string, bool> AllFrameworks = new Dictionary<string, bool>(); foreach (string Framework in LinkEnvironment.Config.Frameworks) { if (!AllFrameworks.ContainsKey(Framework)) { AllFrameworks.Add(Framework, false); } } foreach (UEBuildFramework Framework in LinkEnvironment.Config.AdditionalFrameworks) { if (!AllFrameworks.ContainsKey(Framework.FrameworkName)) { AllFrameworks.Add(Framework.FrameworkName, false); } } foreach (string Framework in LinkEnvironment.Config.WeakFrameworks) { if (!AllFrameworks.ContainsKey(Framework)) { AllFrameworks.Add(Framework, true); } } if (!bIsBuildingLibrary) { foreach (var Framework in AllFrameworks) { LinkCommand += AddFrameworkToLinkCommand(Framework.Key, Framework.Value ? "-weak_framework" : "-framework"); AddLibraryPathToRPaths(Framework.Key, AbsolutePath, ref RPaths, ref LinkCommand, bIsBuildingAppBundle); } } // Add the input files to a response file, and pass the response file on the command-line. List<string> InputFileNames = new List<string>(); foreach (FileItem InputFile in LinkEnvironment.InputFiles) { if (bIsBuildingLibrary) { InputFileNames.Add(string.Format("\"{0}\"", InputFile.AbsolutePath)); } else { string EnginePath = ConvertPath(Path.GetDirectoryName(Directory.GetCurrentDirectory())); string InputFileRelativePath = InputFile.AbsolutePath.Replace(EnginePath, ".."); InputFileNames.Add(string.Format("\"{0}\"", InputFileRelativePath)); } LinkAction.PrerequisiteItems.Add(InputFile); } if (bIsBuildingLibrary) { foreach (string Filename in InputFileNames) { LinkCommand += " " + Filename; } } else { // Write the list of input files to a response file, with a tempfilename, on remote machine string ResponsePath = Path.Combine(LinkEnvironment.Config.IntermediateDirectory, Path.GetFileName(OutputFile.AbsolutePath) + ".response"); // Never create response files when we are only generating IntelliSense data if (!ProjectFileGenerator.bGenerateProjectFiles) { ResponseFile.Create(ResponsePath, InputFileNames); if (BuildHostPlatform.Current.Platform != UnrealTargetPlatform.Mac) { RPCUtilHelper.CopyFile(ResponsePath, ConvertPath(ResponsePath), true); } } LinkCommand += string.Format(" @\"{0}\"", ConvertPath(ResponsePath)); } if (LinkEnvironment.Config.bIsBuildingDLL) { // Add the output file to the command-line. string Filename = ""; int Index = OutputFile.AbsolutePath.LastIndexOf(".app/Contents/MacOS/"); if (Index > -1) { Index += ".app/Contents/MacOS/".Length; Filename = OutputFile.AbsolutePath.Substring(Index); } else { Filename = Path.GetFileName(OutputFile.AbsolutePath); } LinkCommand += string.Format(" -install_name {0}/{1}", DylibsPath, Filename); } if (!bIsBuildingLibrary) { if (UnrealBuildTool.RunningRocket() || (Utils.IsRunningOnMono && LinkEnvironment.Config.bIsCrossReferenced == false)) { foreach (string Library in EngineAndGameLibraries) { string LibraryPath = Library; if (!File.Exists(Library)) { string LibraryDir = Path.GetDirectoryName(Library); string LibraryName = Path.GetFileName(Library); string AppBundleName = "UE4Editor"; if (LibraryName.Contains("UE4Editor-Mac-")) { string[] Parts = LibraryName.Split('-'); AppBundleName += "-" + Parts[1] + "-" + Parts[2]; } AppBundleName += ".app"; LibraryPath = LibraryDir + "/" + AppBundleName + "/Contents/MacOS/" + LibraryName; if (!File.Exists(LibraryPath)) { LibraryPath = Library; } } LinkCommand += " \"" + LibraryPath + "\""; } } else { // Tell linker to ignore unresolved symbols, so we don't have a problem with cross dependent dylibs that do not exist yet. // This is fixed in later step, FixDylibDependencies. LinkCommand += string.Format(" -undefined dynamic_lookup"); } } // Add the output file to the command-line. LinkCommand += string.Format(" -o \"{0}\"", RemoteOutputFile.AbsolutePath); // Add the additional arguments specified by the environment. LinkCommand += LinkEnvironment.Config.AdditionalArguments; if (!bIsBuildingLibrary) { // Fix the paths for third party libs foreach (string Library in ThirdPartyLibraries) { string LibraryFileName = Path.GetFileName(Library); LinkCommand += "; " + ToolchainDir + "install_name_tool -change " + LibraryFileName + " " + DylibsPath + "/" + LibraryFileName + " \"" + ConvertPath(OutputFile.AbsolutePath) + "\""; } } LinkAction.CommandArguments = "-c '" + LinkCommand + "'"; // Only execute linking on the local Mac. LinkAction.bCanExecuteRemotely = false; LinkAction.StatusDescription = Path.GetFileName(OutputFile.AbsolutePath); LinkAction.OutputEventHandler = new DataReceivedEventHandler(RemoteOutputReceivedEventHandler); LinkAction.ProducedItems.Add(RemoteOutputFile); if (!Directory.Exists(LinkEnvironment.Config.IntermediateDirectory)) { return OutputFile; } if (!bIsBuildingLibrary) { // Prepare a script that will run later, once every dylibs and the executable are created. This script will be called by action created in FixDylibDependencies() string FixDylibDepsScriptPath = Path.Combine(LinkEnvironment.Config.LocalShadowDirectory, "FixDylibDependencies.sh"); if (!bHasWipedFixDylibScript) { if (File.Exists(FixDylibDepsScriptPath)) { File.Delete(FixDylibDepsScriptPath); } bHasWipedFixDylibScript = true; } if (!Directory.Exists(LinkEnvironment.Config.LocalShadowDirectory)) { Directory.CreateDirectory(LinkEnvironment.Config.LocalShadowDirectory); } StreamWriter FixDylibDepsScript = File.AppendText(FixDylibDepsScriptPath); if (LinkEnvironment.Config.bIsCrossReferenced || !Utils.IsRunningOnMono) { string EngineAndGameLibrariesString = ""; foreach (string Library in EngineAndGameLibraries) { EngineAndGameLibrariesString += " \"" + Library + "\""; } string FixDylibLine = "pushd \"" + ConvertPath(Directory.GetCurrentDirectory()) + "\" > /dev/null; "; FixDylibLine += string.Format("TIMESTAMP=`stat -n -f \"%Sm\" -t \"%Y%m%d%H%M.%S\" \"{0}\"`; ", RemoteOutputFile.AbsolutePath); FixDylibLine += LinkCommand.Replace("-undefined dynamic_lookup", EngineAndGameLibrariesString).Replace("$", "\\$"); FixDylibLine += string.Format("; touch -t $TIMESTAMP \"{0}\"; if [[ $? -ne 0 ]]; then exit 1; fi; ", RemoteOutputFile.AbsolutePath); FixDylibLine += "popd > /dev/null"; AppendMacLine(FixDylibDepsScript, FixDylibLine); } FixDylibDepsScript.Close(); // Prepare a script that will be called by FinalizeAppBundle.sh to copy all necessary third party dylibs to the app bundle // This is done this way as FinalizeAppBundle.sh script can be created before all the libraries are processed, so // at the time of it's creation we don't have the full list of third party dylibs all modules need. string DylibCopyScriptPath = Path.Combine(LinkEnvironment.Config.IntermediateDirectory, "DylibCopy.sh"); if (!bHasWipedCopyDylibScript) { if (File.Exists(DylibCopyScriptPath)) { File.Delete(DylibCopyScriptPath); } bHasWipedCopyDylibScript = true; } string ExistingScript = File.Exists(DylibCopyScriptPath) ? File.ReadAllText(DylibCopyScriptPath) : ""; StreamWriter DylibCopyScript = File.AppendText(DylibCopyScriptPath); foreach (string Library in ThirdPartyLibraries) { string CopyCommandLineEntry = string.Format("cp -f \"{0}\" \"$1.app/Contents/MacOS\"", ConvertPath(Path.GetFullPath(Library)).Replace("$", "\\$")); if (!ExistingScript.Contains(CopyCommandLineEntry)) { AppendMacLine(DylibCopyScript, CopyCommandLineEntry); } } DylibCopyScript.Close(); // For non-console application, prepare a script that will create the app bundle. It'll be run by FinalizeAppBundle action if (bIsBuildingAppBundle) { string FinalizeAppBundleScriptPath = Path.Combine(LinkEnvironment.Config.IntermediateDirectory, "FinalizeAppBundle.sh"); StreamWriter FinalizeAppBundleScript = File.CreateText(FinalizeAppBundleScriptPath); AppendMacLine(FinalizeAppBundleScript, "#!/bin/sh"); string BinariesPath = Path.GetDirectoryName(OutputFile.AbsolutePath); BinariesPath = Path.GetDirectoryName(BinariesPath.Substring(0, BinariesPath.IndexOf(".app"))); AppendMacLine(FinalizeAppBundleScript, "cd \"{0}\"", ConvertPath(BinariesPath).Replace("$", "\\$")); string ExeName = Path.GetFileName(OutputFile.AbsolutePath); string[] ExeNameParts = ExeName.Split('-'); string GameName = ExeNameParts[0]; AppendMacLine(FinalizeAppBundleScript, "mkdir -p \"{0}.app/Contents/MacOS\"", ExeName); AppendMacLine(FinalizeAppBundleScript, "mkdir -p \"{0}.app/Contents/Resources\"", ExeName); // Copy third party dylibs by calling additional script prepared earlier AppendMacLine(FinalizeAppBundleScript, "sh \"{0}\" \"{1}\"", ConvertPath(DylibCopyScriptPath).Replace("$", "\\$"), ExeName); string IconName = "UE4"; string BundleVersion = ExeName.StartsWith("EpicGamesLauncher") ? LoadLauncherDisplayVersion() : LoadEngineDisplayVersion(); string EngineSourcePath = ConvertPath(Directory.GetCurrentDirectory()).Replace("$", "\\$"); string UProjectFilePath = UProjectInfo.GetProjectFilePath(GameName); string CustomResourcesPath = ""; string CustomBuildPath = ""; if (string.IsNullOrEmpty(UProjectFilePath)) { string[] TargetFiles = Directory.GetFiles(Directory.GetCurrentDirectory(), GameName + ".Target.cs", SearchOption.AllDirectories); if (TargetFiles.Length == 1) { CustomResourcesPath = Path.GetDirectoryName(TargetFiles[0]) + "/Resources/Mac"; CustomBuildPath = Path.GetDirectoryName(TargetFiles[0]) + "../Build/Mac"; } else { Log.TraceWarning("Found {0} Target.cs files for {1} in alldir search of directory {2}", TargetFiles.Length, GameName, Directory.GetCurrentDirectory()); } } else { string ResourceParentFolderName = ExeName.StartsWith("EpicGamesLauncher") ? "Application" : GameName; string FullUProjectFilePath = Path.GetFullPath(UProjectFilePath); CustomResourcesPath = Path.GetDirectoryName(FullUProjectFilePath) + "/Source/" + ResourceParentFolderName + "/Resources/Mac"; CustomBuildPath = Path.GetDirectoryName(FullUProjectFilePath) + "/Build/Mac"; } bool bBuildingEditor = GameName.EndsWith("Editor"); // Copy resources string DefaultIcon = EngineSourcePath + "/Runtime/Launch/Resources/Mac/" + IconName + ".icns"; string CustomIcon = ""; if (bBuildingEditor) { CustomIcon = DefaultIcon; } else { CustomIcon = CustomBuildPath + "/Application.icns"; if (!File.Exists(CustomIcon)) { CustomIcon = CustomResourcesPath + "/" + GameName + ".icns"; if (!File.Exists(CustomIcon)) { CustomIcon = DefaultIcon; } } if (CustomIcon != DefaultIcon) { QueueFileForBatchUpload(FileItem.GetItemByFullPath(Path.GetFullPath(CustomIcon))); CustomIcon = ConvertPath(CustomIcon); } } AppendMacLine(FinalizeAppBundleScript, "cp -f \"{0}\" \"{2}.app/Contents/Resources/{1}.icns\"", CustomIcon, IconName, ExeName); if (ExeName.StartsWith("UE4Editor")) { AppendMacLine(FinalizeAppBundleScript, "cp -f \"{0}/Runtime/Launch/Resources/Mac/UProject.icns\" \"{1}.app/Contents/Resources/UProject.icns\"", EngineSourcePath, ExeName); } string InfoPlistFile = CustomResourcesPath + "/Info.plist"; if (!File.Exists(InfoPlistFile)) { InfoPlistFile = EngineSourcePath + "/Runtime/Launch/Resources/Mac/" + (bBuildingEditor ? "Info-Editor.plist" : "Info.plist"); } else { QueueFileForBatchUpload(FileItem.GetItemByFullPath(Path.GetFullPath(InfoPlistFile))); InfoPlistFile = ConvertPath(InfoPlistFile); } AppendMacLine(FinalizeAppBundleScript, "cp -f \"{0}\" \"{1}.app/Contents/Info.plist\"", InfoPlistFile, ExeName); // Fix contents of Info.plist AppendMacLine(FinalizeAppBundleScript, "sed -i \"\" \"s/\\${0}/{1}/g\" \"{1}.app/Contents/Info.plist\"", "{EXECUTABLE_NAME}", ExeName); AppendMacLine(FinalizeAppBundleScript, "sed -i \"\" \"s/\\${0}/{1}/g\" \"{2}.app/Contents/Info.plist\"", "{APP_NAME}", GameName, ExeName); AppendMacLine(FinalizeAppBundleScript, "sed -i \"\" \"s/\\${0}/{1}/g\" \"{2}.app/Contents/Info.plist\"", "{MACOSX_DEPLOYMENT_TARGET}", MinMacOSVersion, ExeName); AppendMacLine(FinalizeAppBundleScript, "sed -i \"\" \"s/\\${0}/{1}/g\" \"{2}.app/Contents/Info.plist\"", "{ICON_NAME}", IconName, ExeName); AppendMacLine(FinalizeAppBundleScript, "sed -i \"\" \"s/\\${0}/{1}/g\" \"{2}.app/Contents/Info.plist\"", "{BUNDLE_VERSION}", BundleVersion, ExeName); // Generate PkgInfo file AppendMacLine(FinalizeAppBundleScript, "echo 'echo -n \"APPL????\"' | bash > \"{0}.app/Contents/PkgInfo\"", ExeName); // Make sure OS X knows the bundle was updated AppendMacLine(FinalizeAppBundleScript, "touch -c \"{0}.app\"", ExeName); FinalizeAppBundleScript.Close(); // copy over some needed files // @todo mac: Make a QueueDirectoryForBatchUpload QueueFileForBatchUpload(FileItem.GetItemByFullPath(Path.GetFullPath("../../Engine/Source/Runtime/Launch/Resources/Mac/UE4.icns"))); QueueFileForBatchUpload(FileItem.GetItemByFullPath(Path.GetFullPath("../../Engine/Source/Runtime/Launch/Resources/Mac/UProject.icns"))); QueueFileForBatchUpload(FileItem.GetItemByFullPath(Path.GetFullPath("../../Engine/Source/Runtime/Launch/Resources/Mac/Info.plist"))); QueueFileForBatchUpload(FileItem.GetItemByFullPath(Path.Combine(LinkEnvironment.Config.IntermediateDirectory, "DylibCopy.sh"))); } } // For Mac, generate the dSYM file if the config file is set to do so if ((BuildConfiguration.bGeneratedSYMFile == true || BuildConfiguration.bUsePDBFiles == true) && (!bIsBuildingLibrary || LinkEnvironment.Config.bIsBuildingDLL)) { Log.TraceInformation("Generating dSYM file for {0} - this will add some time to your build...", Path.GetFileName(OutputFile.AbsolutePath)); RemoteOutputFile = GenerateDebugInfo(OutputFile); } return RemoteOutputFile; }
public abstract FileItem LinkFiles(LinkEnvironment LinkEnvironment, bool bBuildImportLibraryOnly);
public override FileItem[] LinkAllFiles(LinkEnvironment LinkEnvironment, bool bBuildImportLibraryOnly) { List<FileItem> Outputs = new List<FileItem>(); for (int ArchIndex = 0; ArchIndex < Arches.Count; ArchIndex++) { string Arch = Arches[ArchIndex]; for (int GPUArchIndex = 0; GPUArchIndex < GPUArchitectures.Count; GPUArchIndex++) { string GPUArchitecture = GPUArchitectures[GPUArchIndex]; int OutputPathIndex = ArchIndex * GPUArchitectures.Count + GPUArchIndex; // Android will have an array of outputs if (LinkEnvironment.Config.OutputFilePaths.Count < OutputPathIndex || !Path.GetFileNameWithoutExtension(LinkEnvironment.Config.OutputFilePaths[OutputPathIndex]).EndsWith(Arch + GPUArchitecture)) { throw new BuildException("The OutputFilePaths array didn't match the Arches array in AndroidToolChain.LinkAllFiles"); } // Create an action that invokes the linker. Action LinkAction = new Action(ActionType.Link); LinkAction.WorkingDirectory = Path.GetFullPath("."); if (LinkEnvironment.Config.bIsBuildingLibrary) { switch (Arch) { case "-armv7": LinkAction.CommandPath = ArPathArm; break; case "-arm64": LinkAction.CommandPath = ArPathArm64; break; case "-x86": LinkAction.CommandPath = ArPathx86; ; break; case "-x64": LinkAction.CommandPath = ArPathx64; ; break; default: LinkAction.CommandPath = ArPathArm; ; break; } } else { LinkAction.CommandPath = ClangPath; } string LinkerPath = LinkAction.WorkingDirectory; LinkAction.WorkingDirectory = LinkEnvironment.Config.IntermediateDirectory; // Get link arguments. LinkAction.CommandArguments = LinkEnvironment.Config.bIsBuildingLibrary ? GetArArguments(LinkEnvironment) : GetLinkArguments(LinkEnvironment, Arch); // Add the output file as a production of the link action. FileItem OutputFile; OutputFile = FileItem.GetItemByPath(LinkEnvironment.Config.OutputFilePaths[OutputPathIndex]); Outputs.Add(OutputFile); LinkAction.ProducedItems.Add(OutputFile); LinkAction.StatusDescription = string.Format("{0}", Path.GetFileName(OutputFile.AbsolutePath)); // LinkAction.bPrintDebugInfo = true; // Add the output file to the command-line. if (LinkEnvironment.Config.bIsBuildingLibrary) { LinkAction.CommandArguments += string.Format(" \"{0}\"", OutputFile.AbsolutePath); } else { LinkAction.CommandArguments += string.Format(" -o \"{0}\"", OutputFile.AbsolutePath); } // Add the input files to a response file, and pass the response file on the command-line. List<string> InputFileNames = new List<string>(); foreach (FileItem InputFile in LinkEnvironment.InputFiles) { // make sure it's for current Arch if (Path.GetFileNameWithoutExtension(InputFile.AbsolutePath).EndsWith(Arch + GPUArchitecture)) { string AbsolutePath = InputFile.AbsolutePath.Replace("\\", "/"); AbsolutePath = AbsolutePath.Replace(LinkEnvironment.Config.IntermediateDirectory.Replace("\\", "/"), ""); AbsolutePath = AbsolutePath.TrimStart(new char[] { '/' }); InputFileNames.Add(string.Format("\"{0}\"", AbsolutePath)); LinkAction.PrerequisiteItems.Add(InputFile); } } string ResponseFileName = GetResponseFileName(LinkEnvironment, OutputFile); LinkAction.CommandArguments += string.Format(" @\"{0}\"", ResponseFile.Create(ResponseFileName, InputFileNames)); // libs don't link in other libs if (!LinkEnvironment.Config.bIsBuildingLibrary) { // Add the library paths to the argument list. foreach (string LibraryPath in LinkEnvironment.Config.LibraryPaths) { // LinkerPaths could be relative or absolute string AbsoluteLibraryPath = ActionThread.ExpandEnvironmentVariables(LibraryPath); if (IsDirectoryForArch(AbsoluteLibraryPath, Arch)) { // environment variables aren't expanded when using the $( style if (Path.IsPathRooted(AbsoluteLibraryPath) == false) { AbsoluteLibraryPath = Path.Combine(LinkerPath, AbsoluteLibraryPath); } LinkAction.CommandArguments += string.Format(" -L\"{0}\"", AbsoluteLibraryPath); } } // add libraries in a library group LinkAction.CommandArguments += string.Format(" -Wl,--start-group"); foreach (string AdditionalLibrary in LinkEnvironment.Config.AdditionalLibraries) { if (!ShouldSkipLib(AdditionalLibrary, Arch, GPUArchitecture)) { if (String.IsNullOrEmpty(Path.GetDirectoryName(AdditionalLibrary))) { LinkAction.CommandArguments += string.Format(" \"-l{0}\"", AdditionalLibrary); } else { // full pathed libs are compiled by us, so we depend on linking them LinkAction.CommandArguments += string.Format(" \"{0}\"", Path.GetFullPath(AdditionalLibrary)); LinkAction.PrerequisiteItems.Add(FileItem.GetItemByPath(AdditionalLibrary)); } } } LinkAction.CommandArguments += string.Format(" -Wl,--end-group"); } // Add the additional arguments specified by the environment. LinkAction.CommandArguments += LinkEnvironment.Config.AdditionalArguments; LinkAction.CommandArguments = LinkAction.CommandArguments.Replace("\\", "/"); // Only execute linking on the local PC. LinkAction.bCanExecuteRemotely = false; } } return Outputs.ToArray(); }
static string GetLinkArguments(LinkEnvironment LinkEnvironment) { string Result = GetSharedArguments_Global(LinkEnvironment.Config.Target.Configuration, LinkEnvironment.Config.Target.Architecture); if (LinkEnvironment.Config.Target.Architecture != "-win32") { // enable verbose mode Result += " -v"; if (LinkEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Debug) { // check for alignment/etc checking //Result += " -s SAFE_HEAP=1"; //Result += " -s CHECK_HEAP_ALIGN=1"; //Result += " -s SAFE_DYNCALLS=1"; // enable assertions in non-Shipping/Release builds Result += " -s ASSERTIONS=1"; } if (LinkEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Debug) { Result += " -O0"; } if (LinkEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Debug || LinkEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Development) { Result += " -s GL_ASSERTIONS=1 "; } if (LinkEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Development) { Result += " -O2 -s ASM_JS=1 -s OUTLINING_LIMIT=110000 -g2 "; } if (LinkEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Shipping) { Result += " -O3 -s ASM_JS=1 -s OUTLINING_LIMIT=40000"; } Result += " -s CASE_INSENSITIVE_FS=1 "; string BaseSDKPath = Environment.GetEnvironmentVariable("EMSCRIPTEN"); Result += " --js-library \"" + BaseSDKPath + "/Src/library_openal.js\" "; } return Result; }
static string GetArArguments(LinkEnvironment LinkEnvironment) { string Result = ""; Result += " -r"; return Result; }
public override FileItem LinkFiles(LinkEnvironment LinkEnvironment, bool bBuildImportLibraryOnly) { if (LinkEnvironment.Config.bIsBuildingDotNetAssembly) { return FileItem.GetItemByPath(LinkEnvironment.Config.OutputFilePath); } bool bIsBuildingLibrary = LinkEnvironment.Config.bIsBuildingLibrary || bBuildImportLibraryOnly; bool bIncludeDependentLibrariesInLibrary = bIsBuildingLibrary && LinkEnvironment.Config.bIncludeDependentLibrariesInLibrary; // Create an action that invokes the linker. Action LinkAction = new Action(ActionType.Link); LinkAction.WorkingDirectory = Path.GetFullPath("."); LinkAction.CommandPath = GetVCToolPath( LinkEnvironment.Config.Target.Platform, LinkEnvironment.Config.Target.Configuration, bIsBuildingLibrary ? "lib" : "link"); // Get link arguments. LinkAction.CommandArguments = bIsBuildingLibrary ? GetLibArguments(LinkEnvironment) : GetLinkArguments(LinkEnvironment); // Tell the action that we're building an import library here and it should conditionally be // ignored as a prerequisite for other actions LinkAction.bProducesImportLibrary = bBuildImportLibraryOnly || LinkEnvironment.Config.bIsBuildingDLL; // If we're only building an import library, add the '/DEF' option that tells the LIB utility // to simply create a .LIB file and .EXP file, and don't bother validating imports if (bBuildImportLibraryOnly) { LinkAction.CommandArguments += " /DEF"; // Ensure that the import library references the correct filename for the linked binary. LinkAction.CommandArguments += string.Format(" /NAME:\"{0}\"", Path.GetFileName(LinkEnvironment.Config.OutputFilePath)); } if (!LinkEnvironment.Config.bIsBuildingLibrary || (LinkEnvironment.Config.bIsBuildingLibrary && bIncludeDependentLibrariesInLibrary)) { // Add the library paths to the argument list. foreach (string LibraryPath in LinkEnvironment.Config.LibraryPaths) { LinkAction.CommandArguments += string.Format(" /LIBPATH:\"{0}\"", LibraryPath); } // Add the excluded default libraries to the argument list. foreach (string ExcludedLibrary in LinkEnvironment.Config.ExcludedLibraries) { LinkAction.CommandArguments += string.Format(" /NODEFAULTLIB:\"{0}\"", ExcludedLibrary); } } // For targets that are cross-referenced, we don't want to write a LIB file during the link step as that // file will clobber the import library we went out of our way to generate during an earlier step. This // file is not needed for our builds, but there is no way to prevent MSVC from generating it when // linking targets that have exports. We don't want this to clobber our LIB file and invalidate the // existing timstamp, so instead we simply emit it with a different name string ImportLibraryFilePath = Path.Combine(LinkEnvironment.Config.IntermediateDirectory, Path.GetFileNameWithoutExtension(LinkEnvironment.Config.OutputFilePath) + ".lib"); if (LinkEnvironment.Config.bIsCrossReferenced && !bBuildImportLibraryOnly) { ImportLibraryFilePath += ".suppressed"; } FileItem OutputFile; if (bBuildImportLibraryOnly) { OutputFile = FileItem.GetItemByPath(ImportLibraryFilePath); } else { OutputFile = FileItem.GetItemByPath(LinkEnvironment.Config.OutputFilePath); OutputFile.bNeedsHotReloadNumbersDLLCleanUp = LinkEnvironment.Config.bIsBuildingDLL; } LinkAction.ProducedItems.Add(OutputFile); LinkAction.StatusDescription = Path.GetFileName(OutputFile.AbsolutePath); // Add the input files to a response file, and pass the response file on the command-line. List<string> InputFileNames = new List<string>(); foreach (FileItem InputFile in LinkEnvironment.InputFiles) { InputFileNames.Add(string.Format("\"{0}\"", InputFile.AbsolutePath)); LinkAction.PrerequisiteItems.Add(InputFile); } if (!bBuildImportLibraryOnly) { // Add input libraries as prerequisites, too! foreach (FileItem InputLibrary in LinkEnvironment.InputLibraries) { InputFileNames.Add(string.Format("\"{0}\"", InputLibrary.AbsolutePath)); LinkAction.PrerequisiteItems.Add(InputLibrary); } } if (!bIsBuildingLibrary || (LinkEnvironment.Config.bIsBuildingLibrary && bIncludeDependentLibrariesInLibrary)) { foreach (string AdditionalLibrary in LinkEnvironment.Config.AdditionalLibraries) { InputFileNames.Add(string.Format("\"{0}\"", AdditionalLibrary)); // If the library file name has a relative path attached (rather than relying on additional // lib directories), then we'll add it to our prerequisites list. This will allow UBT to detect // when the binary needs to be relinked because a dependent external library has changed. //if( !String.IsNullOrEmpty( Path.GetDirectoryName( AdditionalLibrary ) ) ) { LinkAction.PrerequisiteItems.Add(FileItem.GetItemByPath(AdditionalLibrary)); } } } // Create a response file for the linker string ResponseFileName = GetResponseFileName(LinkEnvironment, OutputFile); // Never create response files when we are only generating IntelliSense data if (!ProjectFileGenerator.bGenerateProjectFiles) { ResponseFile.Create(ResponseFileName, InputFileNames); } LinkAction.CommandArguments += string.Format(" @\"{0}\"", ResponseFileName); // Add the output file to the command-line. LinkAction.CommandArguments += string.Format(" /OUT:\"{0}\"", OutputFile.AbsolutePath); if (bBuildImportLibraryOnly || (LinkEnvironment.Config.bHasExports && !bIsBuildingLibrary)) { // An export file is written to the output directory implicitly; add it to the produced items list. string ExportFilePath = Path.ChangeExtension(ImportLibraryFilePath, ".exp"); FileItem ExportFile = FileItem.GetItemByPath(ExportFilePath); LinkAction.ProducedItems.Add(ExportFile); } if (!bIsBuildingLibrary) { // Xbox 360 LTCG does not seem to produce those. if (LinkEnvironment.Config.bHasExports && (LinkEnvironment.Config.Target.Configuration != CPPTargetConfiguration.Shipping)) { // Write the import library to the output directory for nFringe support. FileItem ImportLibraryFile = FileItem.GetItemByPath(ImportLibraryFilePath); LinkAction.CommandArguments += string.Format(" /IMPLIB:\"{0}\"", ImportLibraryFilePath); LinkAction.ProducedItems.Add(ImportLibraryFile); } if (LinkEnvironment.Config.bCreateDebugInfo) { // Write the PDB file to the output directory. { string PDBFilePath = Path.Combine(LinkEnvironment.Config.OutputDirectory, Path.GetFileNameWithoutExtension(OutputFile.AbsolutePath) + ".pdb"); FileItem PDBFile = FileItem.GetItemByPath(PDBFilePath); LinkAction.CommandArguments += string.Format(" /PDB:\"{0}\"", PDBFilePath); LinkAction.ProducedItems.Add(PDBFile); } // Write the MAP file to the output directory. #if false if (true) { string MAPFilePath = Path.Combine(LinkEnvironment.Config.OutputDirectory, Path.GetFileNameWithoutExtension(OutputFile.AbsolutePath) + ".map"); FileItem MAPFile = FileItem.GetItemByPath(MAPFilePath); LinkAction.CommandArguments += string.Format(" /MAP:\"{0}\"", MAPFilePath); LinkAction.ProducedItems.Add(MAPFile); } #endif } // Add the additional arguments specified by the environment. LinkAction.CommandArguments += LinkEnvironment.Config.AdditionalArguments; } Log.TraceVerbose(" Linking: " + LinkAction.StatusDescription); Log.TraceVerbose(" Command: " + LinkAction.CommandArguments); // Only execute linking on the local PC. LinkAction.bCanExecuteRemotely = false; return OutputFile; }
private bool SetupGraphicsDebugger(ReadOnlyTargetRules Target, CppCompileEnvironment CompileEnvironment, LinkEnvironment LinkEnvironment) { string AndroidGraphicsDebugger; ConfigHierarchy Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(Target.ProjectFile), UnrealTargetPlatform.Android); Ini.GetString("/Script/AndroidRuntimeSettings.AndroidRuntimeSettings", "AndroidGraphicsDebugger", out AndroidGraphicsDebugger); if (AndroidGraphicsDebugger.ToLower() == "renderdoc") { string RenderDocPath; AndroidPlatformSDK.GetPath(Ini, "/Script/AndroidRuntimeSettings.AndroidRuntimeSettings", "RenderDocPath", out RenderDocPath); string RenderDocLibPath = Path.Combine(RenderDocPath, @"android\lib\armeabi-v7a"); if (Directory.Exists(RenderDocLibPath)) { LinkEnvironment.LibraryPaths.Add(new DirectoryReference(RenderDocLibPath)); LinkEnvironment.AdditionalLibraries.Add("VkLayer_GLES_RenderDoc"); return(true); } } return(false); }
static string GetLibArguments(LinkEnvironment LinkEnvironment) { string Result = ""; // Prevents the linker from displaying its logo for each invocation. Result += " /NOLOGO"; // Prompt the user before reporting internal errors to Microsoft. Result += " /errorReport:prompt"; // Set machine type/ architecture to be 64 bit. Result += " /MACHINE:x64"; Result += " /SUBSYSTEM:WINDOWS"; // // Shipping & LTCG // if (LinkEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Shipping) { // Use link-time code generation. Result += " /ltcg"; } return Result; }