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");
            }
        }
Exemple #2
0
 /// <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);
 }
Exemple #3
0
        /// <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);
            }
        }
Exemple #4
0
        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);
        }
Exemple #5
0
        /// <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));
            }
        }
Exemple #6
0
        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);
        }
Exemple #9
0
        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;
        }
Exemple #12
0
        /// <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;
		}
Exemple #16
0
        /** 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);
        }
Exemple #17
0
        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);
        }
Exemple #18
0
 /// <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);
 }
Exemple #19
0
        /// <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));
        }
Exemple #20
0
        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);
        }
Exemple #21
0
        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);
        }
Exemple #22
0
        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);
        }
Exemple #24
0
 /// <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);
 }
Exemple #25
0
        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;
        }
Exemple #32
0
        /// <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);
            }
        }
Exemple #33
0
        /// <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;
        }
Exemple #45
0
		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;
		}
Exemple #46
0
		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;
        }