예제 #1
0
        /** Copy constructor. */
        protected LinkEnvironment(LinkEnvironment InCopyEnvironment)
        {
            InputFiles.AddRange(InCopyEnvironment.InputFiles);
            InputLibraries.AddRange(InCopyEnvironment.InputLibraries);

            Config = new LinkEnvironmentConfiguration(InCopyEnvironment.Config);
        }
예제 #2
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 (STBuildTool.HasUProjectFile())
            {
                // If this is the uproject being built, redirect the intermediate
                if (Utils.IsFileUnderDirectory(OutputFile.AbsolutePath, STBuildTool.GetUProjectPath()))
                {
                    ResponseFileName = Path.Combine(
                        STBuildTool.GetUProjectPath(),
                        BuildConfiguration.PlatformIntermediateFolder,
                        Path.GetFileNameWithoutExtension(STBuildTool.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;
        }
예제 #3
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 virtual void SetupDependentLinkEnvironment(ref LinkEnvironment DependentLinkEnvironment)
 {
 }
예제 #4
0
 public virtual ICollection<FileItem> PostBuild(FileItem Executable, LinkEnvironment ExecutableLinkEnvironment)
 {
     return new List<FileItem>();
 }
예제 #5
0
 public abstract FileItem LinkFiles(LinkEnvironment LinkEnvironment, bool bBuildImportLibraryOnly);
예제 #6
0
 public virtual FileItem[] LinkAllFiles(LinkEnvironment LinkEnvironment, bool bBuildImportLibraryOnly)
 {
     return new FileItem[] { LinkFiles(LinkEnvironment, bBuildImportLibraryOnly) };
 }
예제 #7
0
        static string GetArchiveArguments_Global(LinkEnvironment LinkEnvironment)
        {
            string Result = "";

            Result += " -static";

            return Result;
        }
예제 #8
0
 /// <summary>
 /// Builds the binary.
 /// </summary>
 /// <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>
 /// <returns></returns>
 public abstract IEnumerable<FileItem> Build(ISTToolChain ToolChain, CPPEnvironment CompileEnvironment, LinkEnvironment LinkEnvironment);
예제 #9
0
        public override void SetupPrivateLinkEnvironment(
            ref LinkEnvironment LinkEnvironment,
            ref List<STBuildBinary> BinaryDependencies,
            ref Dictionary<STBuildModule, bool> VisitedModules
            )
        {
            base.SetupPrivateLinkEnvironment(ref LinkEnvironment, ref BinaryDependencies, ref VisitedModules);

            if (RedistStaticLibraryPaths != null)
            {
                foreach (string LibVar in RedistStaticLibraryPaths)
                {
                    LinkEnvironment.Config.AdditionalLibraries.Add(Path.GetFullPath(LibVar));
                }
            }
        }
예제 #10
0
        // STBuildModule interface.
        public override List<FileItem> Compile(CPPEnvironment GlobalCompileEnvironment, CPPEnvironment CompileEnvironment, bool bCompileMonolithic)
        {
            var BuildPlatform = STBuildPlatform.GetBuildPlatformForCPPTargetPlatform(CompileEnvironment.Config.Target.Platform);

            var LinkInputFiles = new List<FileItem>();
            if (ProjectFileGenerator.bGenerateProjectFiles && IntelliSenseGatherer == null)
            {
                // Nothing to do for IntelliSense, bail out early
                return LinkInputFiles;
            }

            if (RedistStaticLibraryPaths != null && !bBuildingRedistStaticLibrary)
            {
                // The redist static library will be added in SetupPrivateLinkEnvironment
                return LinkInputFiles;
            }

            var ModuleCompileEnvironment = CreateModuleCompileEnvironment(CompileEnvironment);

            if (IntelliSenseGatherer != null)
            {
                // Update project file's set of preprocessor definitions and include paths
                IntelliSenseGatherer.AddIntelliSensePreprocessorDefinitions(ModuleCompileEnvironment.Config.Definitions);
                IntelliSenseGatherer.AddInteliiSenseIncludePaths(ModuleCompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths, bAddingSystemIncludes: true);
                IntelliSenseGatherer.AddInteliiSenseIncludePaths(ModuleCompileEnvironment.Config.CPPIncludeInfo.IncludePaths, bAddingSystemIncludes: false);

                // Bail out.  We don't need to actually compile anything while generating project files.
                return LinkInputFiles;
            }

            // Throw an error if the module's source file list referenced any non-existent files.
            if (SourceFilesToBuild.MissingFiles.Count > 0)
            {
                throw new BuildException(
                    "UBT ERROR: Module \"{0}\" references non-existent files:\n{1} (perhaps a file was added to the project but not checked in)",
                    Name,
                    string.Join("\n", SourceFilesToBuild.MissingFiles.Select(M => M.AbsolutePath))
                );
            }

            // For an executable or a static library do not use the default RC file -
            // If the executable wants it, it will be in their source list anyway.
            // The issue here is that when making a monolithic game, the processing
            // of the other game modules will stomp the game-specific rc file.
            if (Binary.Config.Type == STBuildBinaryType.DynamicLinkLibrary)
            {
                // Add default PCLaunch.rc file if this module has no own resource file specified
                if (SourceFilesToBuild.RCFiles.Count <= 0)
                {
                    string DefRC = Utils.CleanDirectorySeparators(Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), "Runtime/Launch/Resources/Windows/PCLaunch.rc")));
                    FileItem Item = FileItem.GetItemByFullPath(DefRC);
                    SourceFilesToBuild.RCFiles.Add(Item);
                }

                // Always compile in the API version resource separately. This is required for the module manager to detect compatible API versions.
                string ModuleVersionRC = Utils.CleanDirectorySeparators(Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), "Runtime/Core/Resources/Windows/ModuleVersionResource.rc.inl")));
                FileItem ModuleVersionItem = FileItem.GetItemByFullPath(ModuleVersionRC);
                if (!SourceFilesToBuild.RCFiles.Contains(ModuleVersionItem))
                {
                    SourceFilesToBuild.RCFiles.Add(ModuleVersionItem);
                }
            }

            {
                // Process all of the header file dependencies for this module
                this.CachePCHUsageForModuleSourceFiles(ModuleCompileEnvironment);

                // Make sure our RC files have cached includes.
                foreach (var RCFile in SourceFilesToBuild.RCFiles)
                {
                    RCFile.CachedCPPIncludeInfo = ModuleCompileEnvironment.Config.CPPIncludeInfo;
                }
            }

            // Check to see if this is an Engine module (including program or plugin modules).  That is, the module is located under the "Engine" folder
            var IsGameModule = !Utils.IsFileUnderDirectory(this.ModuleDirectory, Path.Combine(ProjectFileGenerator.EngineRelativePath));

            // Should we force a precompiled header to be generated for this module?  Usually, we only bother with a
            // precompiled header if there are at least several source files in the module (after combining them for unity
            // builds.)  But for game modules, it can be convenient to always have a precompiled header to single-file
            // changes to code is really quick to compile.
            int MinFilesUsingPrecompiledHeader = BuildConfiguration.MinFilesUsingPrecompiledHeader;
            if (MinFilesUsingPrecompiledHeaderOverride != 0)
            {
                MinFilesUsingPrecompiledHeader = MinFilesUsingPrecompiledHeaderOverride;
            }
            else if (IsGameModule && BuildConfiguration.bForcePrecompiledHeaderForGameModules)
            {
                // This is a game module with only a small number of source files, so go ahead and force a precompiled header
                // to be generated to make incremental changes to source files as fast as possible for small projects.
                MinFilesUsingPrecompiledHeader = 1;
            }

            // Should we use unity build mode for this module?
            bool bModuleUsesUnityBuild = BuildConfiguration.bUseUnityBuild;
            if (bFasterWithoutUnity)
            {
                bModuleUsesUnityBuild = false;
            }
            else if (!BuildConfiguration.bForceUnityBuild && IsGameModule && SourceFilesToBuild.CPPFiles.Count < BuildConfiguration.MinGameModuleSourceFilesForUnityBuild)
            {
                // Game modules with only a small number of source files are usually better off having faster iteration times
                // on single source file changes, so we forcibly disable unity build for those modules
                bModuleUsesUnityBuild = false;
            }

            // The environment with which to compile the CPP files
            var CPPCompileEnvironment = ModuleCompileEnvironment;

            // Precompiled header support.
            bool bWasModuleCodeCompiled = false;
            if (BuildPlatform.ShouldUsePCHFiles(CompileEnvironment.Config.Target.Platform, CompileEnvironment.Config.Target.Configuration))
            {
                var PCHGenTimerStart = DateTime.UtcNow;

                // The code below will figure out whether this module will either use a "unique PCH" (private PCH that will only be included by
                // this module's code files), or a "shared PCH" (potentially included by many code files in many modules.)  Only one or the other
                // will be used.
                FileItem SharedPCHHeaderFile = null;

                // In the case of a shared PCH, we also need to keep track of which module that PCH's header file is a member of
                string SharedPCHModuleName = String.Empty;

                bool bDisableSharedPCHFiles = (Binary.Config.bCompileMonolithic && CompileEnvironment.Config.bIsBuildingLibrary);
                if (BuildConfiguration.bUseSharedPCHs && bDisableSharedPCHFiles)
                {
                    Log.TraceVerbose("Module '{0}' was not allowed to use Shared PCHs, because we're compiling to a library in monolithic mode", this.Name);
                }

                bool bUseSharedPCHFiles = BuildConfiguration.bUseSharedPCHs && (bDisableSharedPCHFiles == false) && !STBuildTool.BuildingRocket();

                if (bUseSharedPCHFiles)
                {
                    string SharingPCHHeaderFilePath = null;
                    bool bIsASharedPCHModule = bUseSharedPCHFiles && GlobalCompileEnvironment.SharedPCHHeaderFiles.Any(PCH => PCH.Module == this);
                    if (bIsASharedPCHModule)
                    {
                        SharingPCHHeaderFilePath = Path.GetFullPath(Path.Combine(ProjectFileGenerator.RootRelativePath, "Engine", "Source", this.SharedPCHHeaderFile));
                    }

                    // When compiling in modular mode, we can't use a shared PCH file when compiling a module
                    // with exports, because the shared PCH can only have imports in it to work correctly.
                    bool bCanModuleUseOwnSharedPCH = bAllowSharedPCH && bIsASharedPCHModule && bCompileMonolithic && ProcessedDependencies.UniquePCHHeaderFile.AbsolutePath.Equals(SharingPCHHeaderFilePath, StringComparison.InvariantCultureIgnoreCase);
                    if (bAllowSharedPCH && (!bIsASharedPCHModule || bCanModuleUseOwnSharedPCH))
                    {
                        // Figure out which shared PCH tier we're in
                        var DirectDependencyModules = new List<STBuildModule>();
                        {
                            var ReferencedModules = new Dictionary<string, STBuildModule>(StringComparer.InvariantCultureIgnoreCase);
                            this.GetAllDependencyModules(ref ReferencedModules, ref DirectDependencyModules, bIncludeDynamicallyLoaded: false, bForceCircular: false, bOnlyDirectDependencies: true);
                        }

                        int LargestSharedPCHHeaderFileIndex = -1;
                        foreach (var DependencyModule in DirectDependencyModules)
                        {
                            // These Shared PCHs are ordered from least complex to most complex.  We'll start at the last one and search backwards.
                            for (var SharedPCHHeaderFileIndex = GlobalCompileEnvironment.SharedPCHHeaderFiles.Count - 1; SharedPCHHeaderFileIndex > LargestSharedPCHHeaderFileIndex; --SharedPCHHeaderFileIndex)
                            {
                                var CurSharedPCHHeaderFile = GlobalCompileEnvironment.SharedPCHHeaderFiles[SharedPCHHeaderFileIndex];

                                if (DependencyModule == CurSharedPCHHeaderFile.Module ||
                                    (bIsASharedPCHModule && CurSharedPCHHeaderFile.Module == this))	// If we ourselves are a shared PCH module, always at least use our own module as our shared PCH header if we can't find anything better
                                {
                                    SharedPCHModuleName = CurSharedPCHHeaderFile.Module.Name;
                                    SharedPCHHeaderFile = CurSharedPCHHeaderFile.PCHHeaderFile;
                                    LargestSharedPCHHeaderFileIndex = SharedPCHHeaderFileIndex;
                                    break;
                                }
                            }

                            if (LargestSharedPCHHeaderFileIndex == GlobalCompileEnvironment.SharedPCHHeaderFiles.Count - 1)
                            {
                                // We've determined that the module is using our most complex PCH header, so we can early-out
                                break;
                            }
                        }

                        // Did we not find a shared PCH header that is being included by this module?  This could happen if the module is not including Core.h, even indirectly.
                        if (String.IsNullOrEmpty(SharedPCHModuleName))
                        {
                            throw new BuildException("Module {0} doesn't use a Shared PCH!  Please add a dependency on a Shared PCH module to this module's dependency list", this.Name);
                        }
                    }
                    else
                    {
                        Log.TraceVerbose("Module '{0}' cannot create or use Shared PCHs, because it needs its own private PCH", this.Name);
                    }
                }

                // The precompiled header environment for all source files in this module that use a precompiled header, if we even need one
                PrecompileHeaderEnvironment ModulePCHEnvironment = null;

                // If there was one header that was included first by enough C++ files, use it as the precompiled header.
                // Only use precompiled headers for projects with enough files to make the PCH creation worthwhile.
                if (SharedPCHHeaderFile != null || SourceFilesToBuild.CPPFiles.Count >= MinFilesUsingPrecompiledHeader)
                {
                    FileItem PCHToUse;

                    if (SharedPCHHeaderFile != null)
                    {
                        ModulePCHEnvironment = ApplySharedPCH(GlobalCompileEnvironment, CompileEnvironment, ModuleCompileEnvironment, SourceFilesToBuild.CPPFiles, ref SharedPCHHeaderFile);
                        if (ModulePCHEnvironment != null)
                        {
                            // @todo SharedPCH: Ideally we would exhaustively check for a compatible compile environment (definitions, imports/exports, etc)
                            //    Currently, it's possible for the shared PCH to be compiled differently depending on which module UBT happened to have
                            //    include it first during the build phase.  This could create problems with deterministic builds, or turn up compile
                            //    errors unexpectedly due to compile environment differences.
                            Log.TraceVerbose("Module " + Name + " uses existing Shared PCH '" + ModulePCHEnvironment.PrecompiledHeaderIncludeFilename + "' (from module " + ModulePCHEnvironment.ModuleName + ")");
                        }

                        PCHToUse = SharedPCHHeaderFile;
                    }
                    else
                    {
                        PCHToUse = ProcessedDependencies.UniquePCHHeaderFile;
                    }

                    if (PCHToUse != null)
                    {
                        // Update all CPPFiles to point to the PCH
                        foreach (var CPPFile in SourceFilesToBuild.CPPFiles)
                        {
                            CPPFile.PCHHeaderNameInCode = PCHToUse.AbsolutePath;
                            CPPFile.PrecompiledHeaderIncludeFilename = PCHToUse.AbsolutePath;
                        }
                    }

                    // A shared PCH was not already set up for us, so set one up.
                    if (ModulePCHEnvironment == null)
                    {
                        var PCHHeaderFile = ProcessedDependencies.UniquePCHHeaderFile;
                        var PCHModuleName = this.Name;
                        if (SharedPCHHeaderFile != null)
                        {
                            PCHHeaderFile = SharedPCHHeaderFile;
                            PCHModuleName = SharedPCHModuleName;
                        }
                        var PCHHeaderNameInCode = SourceFilesToBuild.CPPFiles[0].PCHHeaderNameInCode;

                        ModulePCHEnvironment = new PrecompileHeaderEnvironment(PCHModuleName, PCHHeaderNameInCode, PCHHeaderFile, ModuleCompileEnvironment.Config.CLRMode, ModuleCompileEnvironment.Config.OptimizeCode);

                        if (SharedPCHHeaderFile != null)
                        {
                            // Add to list of shared PCH environments
                            GlobalCompileEnvironment.SharedPCHEnvironments.Add(ModulePCHEnvironment);
                            Log.TraceVerbose("Module " + Name + " uses new Shared PCH '" + ModulePCHEnvironment.PrecompiledHeaderIncludeFilename + "'");
                        }
                        else
                        {
                            Log.TraceVerbose("Module " + Name + " uses a Unique PCH '" + ModulePCHEnvironment.PrecompiledHeaderIncludeFilename + "'");
                        }
                    }
                }
                else
                {
                    Log.TraceVerbose("Module " + Name + " doesn't use a Shared PCH, and only has " + SourceFilesToBuild.CPPFiles.Count.ToString() + " source file(s).  No Unique PCH will be generated.");
                }

                // Compile the C++ source or the unity C++ files that use a PCH environment.
                if (ModulePCHEnvironment != null)
                {
                    // Setup a new compile environment for this module's source files.  It's pretty much the exact same as the
                    // module's compile environment, except that it will include a PCH file.

                    var ModulePCHCompileEnvironment = ModuleCompileEnvironment.DeepCopy();
                    ModulePCHCompileEnvironment.Config.PrecompiledHeaderAction = PrecompiledHeaderAction.Include;
                    ModulePCHCompileEnvironment.Config.PrecompiledHeaderIncludeFilename = ModulePCHEnvironment.PrecompiledHeaderIncludeFilename.AbsolutePath;
                    ModulePCHCompileEnvironment.Config.PCHHeaderNameInCode = ModulePCHEnvironment.PCHHeaderNameInCode;

                    if (SharedPCHHeaderFile != null)
                    {
                        // Shared PCH headers need to be force included, because we're basically forcing the module to use
                        // the precompiled header that we want, instead of the "first include" in each respective .cpp file
                        ModulePCHCompileEnvironment.Config.bForceIncludePrecompiledHeader = true;
                    }

                    var CPPFilesToBuild = SourceFilesToBuild.CPPFiles;
                    if (bModuleUsesUnityBuild)
                    {
                        // unity files generated for only the set of files which share the same PCH environment
                        CPPFilesToBuild = Unity.GenerateUnityCPPs(Target, CPPFilesToBuild, ModulePCHCompileEnvironment, Name);
                    }

                    // Check if there are enough unity files to warrant pch generation (and we haven't already generated the shared one)
                    if (ModulePCHEnvironment.PrecompiledHeaderFile == null)
                    {
                        if (SharedPCHHeaderFile != null || CPPFilesToBuild.Count >= MinFilesUsingPrecompiledHeader)
                        {
                            bool bAllowDLLExports = true;
                            var PCHOutputDirectory = ModuleCompileEnvironment.Config.OutputDirectory;
                            var PCHModuleName = this.Name;

                            if (SharedPCHHeaderFile != null)
                            {
                                // Disallow DLLExports when generating shared PCHs.  These headers aren't able to export anything, because they're potentially shared between many modules.
                                bAllowDLLExports = false;

                                // Save shared PCHs to a specific folder
                                PCHOutputDirectory = Path.Combine(CompileEnvironment.Config.OutputDirectory, "SharedPCHs");

                                // Use a fake module name for "shared" PCHs.  It may be used by many modules, so we don't want to use this module's name.
                                PCHModuleName = "Shared";
                            }

                            var PCHOutput = PrecompileHeaderEnvironment.GeneratePCHCreationAction(
                                Target,
                                CPPFilesToBuild[0].PCHHeaderNameInCode,
                                ModulePCHEnvironment.PrecompiledHeaderIncludeFilename,
                                ModuleCompileEnvironment,
                                PCHOutputDirectory,
                                PCHModuleName,
                                bAllowDLLExports);
                            ModulePCHEnvironment.PrecompiledHeaderFile = PCHOutput.PrecompiledHeaderFile;

                            ModulePCHEnvironment.OutputObjectFiles.Clear();
                            ModulePCHEnvironment.OutputObjectFiles.AddRange(PCHOutput.ObjectFiles);
                        }
                        else if (CPPFilesToBuild.Count < MinFilesUsingPrecompiledHeader)
                        {
                            Log.TraceVerbose("Module " + Name + " doesn't use a Shared PCH, and only has " + CPPFilesToBuild.Count.ToString() + " unity source file(s).  No Unique PCH will be generated.");
                        }
                    }

                    if (ModulePCHEnvironment.PrecompiledHeaderFile != null)
                    {
                        // Link in the object files produced by creating the precompiled header.
                        LinkInputFiles.AddRange(ModulePCHEnvironment.OutputObjectFiles);

                        // if pch action was generated for the environment then use pch
                        ModulePCHCompileEnvironment.PrecompiledHeaderFile = ModulePCHEnvironment.PrecompiledHeaderFile;

                        // Use this compile environment from now on
                        CPPCompileEnvironment = ModulePCHCompileEnvironment;
                    }

                    LinkInputFiles.AddRange(CPPCompileEnvironment.CompileFiles(Target, CPPFilesToBuild, Name).ObjectFiles);
                    bWasModuleCodeCompiled = true;
                }

                if (BuildConfiguration.bPrintPerformanceInfo)
                {
                    var PCHGenTime = (DateTime.UtcNow - PCHGenTimerStart).TotalSeconds;
                    TotalPCHGenTime += PCHGenTime;
                }
            }

            if (!bWasModuleCodeCompiled && SourceFilesToBuild.CPPFiles.Count > 0)
            {
                var CPPFilesToCompile = SourceFilesToBuild.CPPFiles;
                if (bModuleUsesUnityBuild)
                {
                    CPPFilesToCompile = Unity.GenerateUnityCPPs(Target, CPPFilesToCompile, CPPCompileEnvironment, Name);
                }
                LinkInputFiles.AddRange(CPPCompileEnvironment.CompileFiles(Target, CPPFilesToCompile, Name).ObjectFiles);
            }

            if (AutoGenerateCppInfo != null && AutoGenerateCppInfo.BuildInfo != null && !CPPCompileEnvironment.bHackHeaderGenerator)
            {
                string[] GeneratedFiles = Directory.GetFiles(Path.GetDirectoryName(AutoGenerateCppInfo.BuildInfo.FileWildcard), Path.GetFileName(AutoGenerateCppInfo.BuildInfo.FileWildcard));
                foreach (string GeneratedFilename in GeneratedFiles)
                {
                    var GeneratedCppFileItem = FileItem.GetItemByPath(GeneratedFilename);

                    CachePCHUsageForModuleSourceFile(this.Target, CPPCompileEnvironment, GeneratedCppFileItem);

                    // @todo fastubt: Check for ALL other places where we might be injecting .cpp or .rc files for compiling without caching CachedCPPIncludeInfo first (anything platform specfic?)
                    LinkInputFiles.AddRange(CPPCompileEnvironment.CompileFiles(Target, new List<FileItem> { GeneratedCppFileItem }, Name).ObjectFiles);
                }
            }

            // Compile C files directly.
            LinkInputFiles.AddRange(CPPCompileEnvironment.CompileFiles(Target, SourceFilesToBuild.CFiles, Name).ObjectFiles);

            // Compile CC files directly.
            LinkInputFiles.AddRange(CPPCompileEnvironment.CompileFiles(Target, SourceFilesToBuild.CCFiles, Name).ObjectFiles);

            // Compile MM files directly.
            LinkInputFiles.AddRange(CPPCompileEnvironment.CompileFiles(Target, SourceFilesToBuild.MMFiles, Name).ObjectFiles);

            // If we're building Rocket, generate a static library for this module
            if (RedistStaticLibraryPaths != null)
            {
                // Create a link environment for it
                LinkEnvironment RedistLinkEnvironment = new LinkEnvironment();
                RedistLinkEnvironment.InputFiles.AddRange(LinkInputFiles);
                RedistLinkEnvironment.Config.Target = CompileEnvironment.Config.Target;
                RedistLinkEnvironment.Config.bIsBuildingDLL = false;
                RedistLinkEnvironment.Config.bIsBuildingLibrary = true;
                RedistLinkEnvironment.Config.IntermediateDirectory = Binary.Config.IntermediateDirectory;
                RedistLinkEnvironment.Config.OutputFilePaths = RedistStaticLibraryPaths != null ? (string[])RedistStaticLibraryPaths.Clone() : null;

                // Replace the items built so far with the library
                RedistLinkEnvironment.LinkExecutable(false);
                LinkInputFiles.Clear();
            }

            // Compile RC files.
            LinkInputFiles.AddRange(CPPCompileEnvironment.CompileRCFiles(Target, SourceFilesToBuild.RCFiles).ObjectFiles);

            return LinkInputFiles;
        }
예제 #11
0
        public override FileItem LinkFiles(LinkEnvironment LinkEnvironment, bool bBuildImportLibraryOnly)
        {
            var EnvVars = VCEnvironment.SetEnvironment(LinkEnvironment.Config.Target.Platform);

            if (LinkEnvironment.Config.bIsBuildingDotNetAssembly)
            {
                return FileItem.GetItemByPath(LinkEnvironment.Config.OutputFilePath);
            }

            bool bIsBuildingLibrary = LinkEnvironment.Config.bIsBuildingLibrary || bBuildImportLibraryOnly;
            bool bIncludeDependentLibrariesInLibrary = bIsBuildingLibrary && LinkEnvironment.Config.bIncludeDependentLibrariesInLibrary;

            // Get link arguments.
            StringBuilder Arguments = new StringBuilder();
            if (bIsBuildingLibrary)
            {
                AppendLibArguments(LinkEnvironment, Arguments);
            }
            else
            {
                AppendLinkArguments(LinkEnvironment, Arguments);
            }

            // 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)
            {
                Arguments.Append(" /DEF");

                // Ensure that the import library references the correct filename for the linked binary.
                Arguments.AppendFormat(" /NAME:\"{0}\"", Path.GetFileName(LinkEnvironment.Config.OutputFilePath));
            }

            // Add delay loaded DLLs.
            if (!bIsBuildingLibrary)
            {
                // Delay-load these DLLs.
                foreach (string DelayLoadDLL in LinkEnvironment.Config.DelayLoadDLLs)
                {
                    Arguments.AppendFormat(" /DELAYLOAD:\"{0}\"", DelayLoadDLL);
                }
            }

            // @todo UE4 DLL: Why do I need LIBPATHs to build only export libraries with /DEF? (tbbmalloc.lib)
            if (!LinkEnvironment.Config.bIsBuildingLibrary || (LinkEnvironment.Config.bIsBuildingLibrary && bIncludeDependentLibrariesInLibrary))
            {
                // Add the library paths to the argument list.
                foreach (string LibraryPath in LinkEnvironment.Config.LibraryPaths)
                {
                    Arguments.AppendFormat(" /LIBPATH:\"{0}\"", LibraryPath);
                }

                // Add the excluded default libraries to the argument list.
                foreach (string ExcludedLibrary in LinkEnvironment.Config.ExcludedLibraries)
                {
                    Arguments.AppendFormat(" /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;
            }

            List<FileItem> ProducedItems = new List<FileItem>();
            ProducedItems.Add(OutputFile);

            List<FileItem> PrerequisiteItems = new List<FileItem>();

            // 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));
                PrerequisiteItems.Add(InputFile);
            }

            if (!bBuildImportLibraryOnly)
            {
                // Add input libraries as prerequisites, too!
                foreach (FileItem InputLibrary in LinkEnvironment.InputLibraries)
                {
                    InputFileNames.Add(string.Format("\"{0}\"", InputLibrary.AbsolutePath));
                    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 ) ) )
                    {
                        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);
            }
            Arguments.AppendFormat(" @\"{0}\"", ResponseFileName);

            // Add the output file to the command-line.
            Arguments.AppendFormat(" /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);
                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);
                    Arguments.AppendFormat(" /IMPLIB:\"{0}\"", ImportLibraryFilePath);
                    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);
                        Arguments.AppendFormat(" /PDB:\"{0}\"", PDBFilePath);
                        ProducedItems.Add(PDBFile);
                    }

                    // Write a stripped PDB file for Rocket
                    if (STBuildTool.BuildingRocket())
                    {
                        string StrippedPDBFilePath = Path.Combine(LinkEnvironment.Config.OutputDirectory, Path.GetFileNameWithoutExtension(OutputFile.AbsolutePath) + "-Stripped.pdb");
                        FileItem StrippedPDBFile = FileItem.GetItemByPath(StrippedPDBFilePath);
                        Arguments.AppendFormat(" /PDBSTRIPPED:\"{0}\"", StrippedPDBFilePath);
                        ProducedItems.Add(StrippedPDBFile);
                    }

                    // 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.
                Arguments.Append(LinkEnvironment.Config.AdditionalArguments);
            }

            // Create an action that invokes the linker.
            Action LinkAction = new Action(ActionType.Link);
            LinkAction.CommandDescription = "Link";
            LinkAction.WorkingDirectory = Path.GetFullPath(".");
            LinkAction.CommandPath = bIsBuildingLibrary ? EnvVars.LibraryLinkerPath : EnvVars.LinkerPath;
            LinkAction.CommandArguments = Arguments.ToString();
            LinkAction.ProducedItems.AddRange(ProducedItems);
            LinkAction.PrerequisiteItems.AddRange(PrerequisiteItems);
            LinkAction.StatusDescription = Path.GetFileName(OutputFile.AbsolutePath);

            if (WindowsPlatform.bCompileWithClang)
            {
                LinkAction.OutputEventHandler = new DataReceivedEventHandler(ClangCompilerOutputFormatter);
            }

            // 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;

            // Allow remote linking.  Especially in modular builds with many small DLL files, this is almost always very efficient
            LinkAction.bCanExecuteRemotely = true;

            Log.TraceVerbose("     Linking: " + LinkAction.StatusDescription);
            Log.TraceVerbose("     Command: " + LinkAction.CommandArguments);

            return OutputFile;
        }
예제 #12
0
        static void AppendLinkArguments(LinkEnvironment LinkEnvironment, StringBuilder Arguments)
        {
            if (WindowsPlatform.bCompileWithClang && WindowsPlatform.bAllowClangLinker)
            {
                // This tells LLD to run in "Windows emulation" mode, meaning that it will accept MSVC Link arguments
                Arguments.Append(" -flavor link");

                // @todo clang: The following static libraries aren't linking correctly with Clang:
                //		tbbmalloc.lib, zlib_64.lib, libpng_64.lib, freetype2412MT.lib, IlmImf.lib
                //		LLD: Assertion failed: result.size() == 1, file ..\tools\lld\lib\ReaderWriter\FileArchive.cpp, line 71
            }

            // Don't create a side-by-side manifest file for the executable.
            Arguments.Append(" /MANIFEST:NO");

            // Prevents the linker from displaying its logo for each invocation.
            Arguments.Append(" /NOLOGO");

            if (LinkEnvironment.Config.bCreateDebugInfo)
            {
                // Output debug info for the linked executable.
                Arguments.Append(" /DEBUG");
            }

            // Prompt the user before reporting internal errors to Microsoft.
            Arguments.Append(" /errorReport:prompt");

            //
            //	PC
            //
            if ((LinkEnvironment.Config.Target.Platform == CPPTargetPlatform.Win32) ||
                (LinkEnvironment.Config.Target.Platform == CPPTargetPlatform.Win64))
            {
                // Set machine type/ architecture to be 64 bit.
                if (LinkEnvironment.Config.Target.Platform == CPPTargetPlatform.Win64)
                {
                    Arguments.Append(" /MACHINE:x64");
                }
                // 32 bit executable/ target.
                else
                {
                    Arguments.Append(" /MACHINE:x86");
                }

                {
                    if (LinkEnvironment.Config.bIsBuildingConsoleApplication)
                    {
                        Arguments.Append(" /SUBSYSTEM:CONSOLE");
                    }
                    else
                    {
                        Arguments.Append(" /SUBSYSTEM:WINDOWS");
                    }

                    // When targeting Windows XP in Visual Studio 2012+, we need to tell the linker we are going to support execution
                    // on that older platform.  The compiler defaults to version 6.0+.  We'll modify the SUBSYSTEM parameter here.
                    if (WindowsPlatform.IsWindowsXPSupported())
                    {
                        Arguments.Append(LinkEnvironment.Config.Target.Platform == CPPTargetPlatform.Win64 ? ",5.02" : ",5.01");
                    }
                }

                if (LinkEnvironment.Config.bIsBuildingConsoleApplication && !LinkEnvironment.Config.bIsBuildingDLL && !String.IsNullOrEmpty(LinkEnvironment.Config.WindowsEntryPointOverride))
                {
                    // Use overridden entry point
                    Arguments.Append(" /ENTRY:" + LinkEnvironment.Config.WindowsEntryPointOverride);
                }

                // Allow the OS to load the EXE at different base addresses than its preferred base address.
                Arguments.Append(" /FIXED:No");

                // Option is only relevant with 32 bit toolchain.
                if (LinkEnvironment.Config.Target.Platform == CPPTargetPlatform.Win32)
                {
                    // Disables the 2GB address space limit on 64-bit Windows and 32-bit Windows with /3GB specified in boot.ini
                    Arguments.Append(" /LARGEADDRESSAWARE");
                }

                // Explicitly declare that the executable is compatible with Data Execution Prevention.
                Arguments.Append(" /NXCOMPAT");

                // Set the default stack size.
                Arguments.Append(" /STACK:5000000");

                // E&C can't use /SAFESEH.  Also, /SAFESEH isn't compatible with 64-bit linking
                if (!BuildConfiguration.bSupportEditAndContinue &&
                    LinkEnvironment.Config.Target.Platform != CPPTargetPlatform.Win64)
                {
                    // Generates a table of Safe Exception Handlers.  Documentation isn't clear whether they actually mean
                    // Structured Exception Handlers.
                    Arguments.Append(" /SAFESEH");
                }

                // Allow delay-loaded DLLs to be explicitly unloaded.
                Arguments.Append(" /DELAY:UNLOAD");

                if (LinkEnvironment.Config.bIsBuildingDLL)
                {
                    Arguments.Append(" /DLL");
                }

                if (LinkEnvironment.Config.CLRMode == CPPCLRMode.CLREnabled)
                {
                    // DLLs built with managed code aren't allowed to have entry points as they will try to initialize
                    // complex static variables.  Managed code isn't allowed to run during DLLMain, we can't allow
                    // these variables to be initialized here.
                    if (LinkEnvironment.Config.bIsBuildingDLL)
                    {
                        // NOTE: This appears to only be needed if we want to get call stacks for debugging exit crashes related to the above
                        //		Result += " /NOENTRY /NODEFAULTLIB:nochkclr.obj";
                    }
                }
            }

            // Don't embed the full PDB path in the binary when building Rocket executables; the location on disk won't match the user's install directory.
            if (STBuildTool.BuildingRocket())
            {
                Arguments.Append(" /PDBALTPATH:%_PDB%");
            }

            //
            //	Shipping & LTCG
            //
            if (BuildConfiguration.bAllowLTCG &&
                LinkEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Shipping)
            {
                // Use link-time code generation.
                Arguments.Append(" /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.
                Arguments.Append(" /RELEASE");

                // Eliminate unreferenced symbols.
                Arguments.Append(" /OPT:REF");

                // Remove redundant COMDATs.
                Arguments.Append(" /OPT:ICF");
            }
            //
            //	Regular development binary.
            //
            else
            {
                // Keep symbols that are unreferenced.
                Arguments.Append(" /OPT:NOREF");

                // Disable identical COMDAT folding.
                Arguments.Append(" /OPT:NOICF");
            }

            // Enable incremental linking if wanted.
            // NOTE: Don't bother using incremental linking for C++/CLI projects, as that's not supported and the option
            //		 will silently be ignored anyway
            if (BuildConfiguration.bUseIncrementalLinking && LinkEnvironment.Config.CLRMode != CPPCLRMode.CLREnabled)
            {
                Arguments.Append(" /INCREMENTAL");
            }
            else
            {
                Arguments.Append(" /INCREMENTAL:NO");
            }

            // Disable
            //LINK : warning LNK4199: /DELAYLOAD:nvtt_64.dll ignored; no imports found from nvtt_64.dll
            // type warning as we leverage the DelayLoad option to put third-party DLLs into a
            // non-standard location. This requires the module(s) that use said DLL to ensure that it
            // is loaded prior to using it.
            Arguments.Append(" /ignore:4199");

            // Suppress warnings about missing PDB files for statically linked libraries.  We often don't want to distribute
            // PDB files for these libraries.
            Arguments.Append(" /ignore:4099");		// warning LNK4099: PDB '<file>' was not found with '<file>'
        }
예제 #13
0
        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
            //
            if (LinkEnvironment.Config.Target.Platform == CPPTargetPlatform.Win32 || LinkEnvironment.Config.Target.Platform == CPPTargetPlatform.Win64)
            {
                // Set machine type/ architecture to be 64 bit.
                if (LinkEnvironment.Config.Target.Platform == CPPTargetPlatform.Win64)
                {
                    Arguments.Append(" /MACHINE:x64");
                }
                // 32 bit executable/ target.
                else
                {
                    Arguments.Append(" /MACHINE:x86");
                }

                {
                    if (LinkEnvironment.Config.bIsBuildingConsoleApplication)
                    {
                        Arguments.Append(" /SUBSYSTEM:CONSOLE");
                    }
                    else
                    {
                        Arguments.Append(" /SUBSYSTEM:WINDOWS");
                    }

                    // When targeting Windows XP in Visual Studio 2012+, we need to tell the linker we are going to support execution
                    // on that older platform.  The compiler defaults to version 6.0+.  We'll modify the SUBSYSTEM parameter here.
                    if (WindowsPlatform.IsWindowsXPSupported())
                    {
                        Arguments.Append(LinkEnvironment.Config.Target.Platform == CPPTargetPlatform.Win64 ? ",5.02" : ",5.01");
                    }
                }
            }

            //
            //	Shipping & LTCG
            //
            if (LinkEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Shipping)
            {
                // Use link-time code generation.
                Arguments.Append(" /LTCG");
            }
        }
예제 #14
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 != STTargetPlatform.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 != STTargetPlatform.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 ( STBuildFramework 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 != STTargetPlatform.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
            {
                string ResponsePath = Path.GetFullPath("..\\Intermediate\\IOS\\LinkFileList_" + Path.GetFileNameWithoutExtension(LinkEnvironment.Config.OutputFilePath) + ".tmp");
                if (!Utils.IsRunningOnMono && BuildHostPlatform.Current.Platform != STTargetPlatform.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;
        }
예제 #15
0
        string GetLinkArguments_Global( LinkEnvironment LinkEnvironment )
        {
            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=" + BuildIOSVersion;
            Result += " -Wl,-no_pie";
            //			Result += " -v";

            // link in the frameworks
            foreach (string Framework in LinkEnvironment.Config.Frameworks)
            {
                Result += " -framework " + Framework;
            }
            foreach (STBuildFramework 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;
        }
예제 #16
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(ISTToolChain TargetToolChain, CPPEnvironment CompileEnvironment, LinkEnvironment LinkEnvironment)
        {
            // Determine the type of binary we're linking.
            switch (Config.Type)
            {
                case STBuildBinaryType.DynamicLinkLibrary:
                    CompileEnvironment.Config.bIsBuildingDLL = true;
                    CompileEnvironment.Config.bIsBuildingLibrary = false;
                    break;
                case STBuildBinaryType.StaticLibrary:
                    CompileEnvironment.Config.bIsBuildingDLL = false;
                    CompileEnvironment.Config.bIsBuildingLibrary = true;
                    break;
                default:
                    CompileEnvironment.Config.bIsBuildingDLL = false;
                    CompileEnvironment.Config.bIsBuildingLibrary = false;
                    break;
            };

            var OutputFiles = new List<FileItem>();

            var BinaryCompileEnvironment = CompileEnvironment.DeepCopy();
            var BinaryLinkEnvironment = LinkEnvironment.DeepCopy();

            // Process each module that is linked into the binary.
            var BinaryDependencies = new List<STBuildBinary>();
            var LinkEnvironmentVisitedModules = new Dictionary<STBuildModule, bool>();

            // @Hack: This to prevent UHT from listing CoreUObject.generated.cpp as its dependency.
            // We flag the compile environment when we build UHT so that we don't need to check
            // this for each file when generating their dependencies.
            BinaryCompileEnvironment.bHackHeaderGenerator = (Target.GetAppName() == "UnrealHeaderTool");

            // @todo: This should be in some Windows code somewhere...
            // Set the original file name macro; used in PCLaunch.rc to set the binary metadata fields.
            var OriginalFilename = (Config.OriginalOutputFilePaths != null) ?
                Path.GetFileName(Config.OriginalOutputFilePaths[0]) :
                Path.GetFileName(Config.OutputFilePaths[0]);
            BinaryCompileEnvironment.Config.Definitions.Add("ORIGINAL_FILE_NAME=\"" + OriginalFilename + "\"");

            foreach (var ModuleName in ModuleNames)
            {
                var Module = Target.GetModuleByName(ModuleName);

                // Compile each module.
                Log.TraceVerbose("Compile module: " + ModuleName);

                var LinkInputFiles = Module.Compile(CompileEnvironment, BinaryCompileEnvironment, Config.bCompileMonolithic);

                // NOTE: Because of 'Shared PCHs', in monolithic builds the same PCH file may appear as a link input
                // multiple times for a single binary.  We'll check for that here, and only add it once.  This avoids
                // a linker warning about redundant .obj files.
                foreach (var LinkInputFile in LinkInputFiles)
                {
                    if (!BinaryLinkEnvironment.InputFiles.Contains(LinkInputFile))
                    {
                        BinaryLinkEnvironment.InputFiles.Add(LinkInputFile);
                    }
                }

                // Allow the module to modify the link environment for the binary.
                Module.SetupPrivateLinkEnvironment(ref BinaryLinkEnvironment, ref BinaryDependencies, ref LinkEnvironmentVisitedModules);
            }

            // Remove the default resource file on Windows (PCLaunch.rc) if the user has specified their own
            if (BinaryLinkEnvironment.InputFiles.Select(Item => Path.GetFileName(Item.AbsolutePath).ToLower()).Any(Name => Name.EndsWith(".res") && !Name.EndsWith(".inl.res") && Name != "pclaunch.rc.res"))
            {
                BinaryLinkEnvironment.InputFiles.RemoveAll(x => Path.GetFileName(x.AbsolutePath).ToLower() == "pclaunch.rc.res");
            }

            // Allow the binary dependencies to modify the link environment.
            foreach (var BinaryDependency in BinaryDependencies)
            {
                BinaryDependency.SetupDependentLinkEnvironment(ref BinaryLinkEnvironment);
            }

            // Set the link output file.
            BinaryLinkEnvironment.Config.OutputFilePaths = Config.OutputFilePaths != null ? (string[])Config.OutputFilePaths.Clone() : null;

            // Set whether the link is allowed to have exports.
            BinaryLinkEnvironment.Config.bHasExports = Config.bAllowExports;

            // Set the output folder for intermediate files
            BinaryLinkEnvironment.Config.IntermediateDirectory = Config.IntermediateDirectory;

            // Put the non-executable output files (PDB, import library, etc) in the same directory as the production
            BinaryLinkEnvironment.Config.OutputDirectory = Path.GetDirectoryName(Config.OutputFilePaths[0]);

            // Determine the type of binary we're linking.
            switch (Config.Type)
            {
                case STBuildBinaryType.DynamicLinkLibrary:
                    BinaryLinkEnvironment.Config.bIsBuildingDLL = true;
                    BinaryLinkEnvironment.Config.bIsBuildingLibrary = false;
                    break;
                case STBuildBinaryType.StaticLibrary:
                    BinaryLinkEnvironment.Config.bIsBuildingDLL = false;
                    BinaryLinkEnvironment.Config.bIsBuildingLibrary = true;
                    break;
                default:
                    BinaryLinkEnvironment.Config.bIsBuildingDLL = false;
                    BinaryLinkEnvironment.Config.bIsBuildingLibrary = false;
                    break;
            };

            if (ProjectFileGenerator.bGenerateProjectFiles)
            {
                // We're generating projects.  Since we only need include paths and definitions, there is no need
                // to go ahead and run through the linking logic.
                OutputFiles = BinaryLinkEnvironment.InputFiles;
            }
            else if (BuildConfiguration.bEnableCodeAnalysis)
            {
                // We're only analyzing code, so we won't actually link any executables.  Instead, our output
                // files will simply be the .obj files that were compiled during static analysis.
                OutputFiles = BinaryLinkEnvironment.InputFiles;
            }
            else
            {
                if (bCreateImportLibrarySeparately)
                {
                    // Mark the link environment as cross-referenced.
                    BinaryLinkEnvironment.Config.bIsCrossReferenced = true;

                    if (BinaryLinkEnvironment.Config.Target.Platform != CPPTargetPlatform.Mac && BinaryLinkEnvironment.Config.Target.Platform != CPPTargetPlatform.Linux)
                    {
                        // Create the import library.
                        OutputFiles.AddRange(BinaryLinkEnvironment.LinkExecutable(true));
                    }
                }

                BinaryLinkEnvironment.Config.bIncludeDependentLibrariesInLibrary = bIncludeDependentLibrariesInLibrary;

                // Link the binary.
                FileItem[] Executables = BinaryLinkEnvironment.LinkExecutable(false);
                OutputFiles.AddRange(Executables);

                // Produce additional console app if requested
                if (BinaryLinkEnvironment.Config.CanProduceAdditionalConsoleApp && STBuildConfiguration.bBuildEditor)
                {
                    // Produce additional binary but link it as a console app
                    var ConsoleAppLinkEvironment = BinaryLinkEnvironment.DeepCopy();
                    ConsoleAppLinkEvironment.Config.bIsBuildingConsoleApplication = true;
                    ConsoleAppLinkEvironment.Config.WindowsEntryPointOverride = "WinMainCRTStartup";		// For WinMain() instead of "main()" for Launch module
                    for (int Index = 0; Index < Config.OutputFilePaths.Length; Index++)
                    {
                        ConsoleAppLinkEvironment.Config.OutputFilePaths[Index] = GetAdditionalConsoleAppPath(ConsoleAppLinkEvironment.Config.OutputFilePaths[Index]);
                    }

                    // Link the console app executable
                    OutputFiles.AddRange(ConsoleAppLinkEvironment.LinkExecutable(false));
                }

                foreach (var Executable in Executables)
                {
                    OutputFiles.AddRange(TargetToolChain.PostBuild(Executable, BinaryLinkEnvironment));
                }
            }

            return OutputFiles;
        }
예제 #17
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(ref LinkEnvironment DependentLinkEnvironment)
 {
     foreach (string OutputFilePath in Config.OutputFilePaths)
     {
         string LibraryFileName;
         if (Config.Type == STBuildBinaryType.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);
     }
 }
예제 #18
0
        public override void SetupPrivateLinkEnvironment(
            ref LinkEnvironment LinkEnvironment,
            ref List<STBuildBinary> BinaryDependencies,
            ref Dictionary<STBuildModule, bool> VisitedModules
            )
        {
            base.SetupPrivateLinkEnvironment(ref LinkEnvironment, ref BinaryDependencies, ref VisitedModules);

            // Setup the link environment for linking a CLR binary.
            LinkEnvironment.Config.CLRMode = CPPCLRMode.CLREnabled;
        }
예제 #19
0
        /// <summary>
        /// Builds the binary.
        /// </summary>
        /// <param name="ToolChain">The toolchain 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>
        /// <returns></returns>
        public override IEnumerable<FileItem> Build(ISTToolChain ToolChain, CPPEnvironment CompileEnvironment, LinkEnvironment LinkEnvironment)
        {
            var ProjectCSharpEnviroment = new CSharpEnvironment();
            if (LinkEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Debug)
            {
                ProjectCSharpEnviroment.TargetConfiguration = CSharpTargetConfiguration.Debug;
            }
            else
            {
                ProjectCSharpEnviroment.TargetConfiguration = CSharpTargetConfiguration.Development;
            }
            ProjectCSharpEnviroment.EnvironmentTargetPlatform = LinkEnvironment.Config.Target.Platform;

            // Currently only supported by windows...
            STToolChain.GetPlatformToolChain(CPPTargetPlatform.Win64).CompileCSharpProject(
                ProjectCSharpEnviroment, Config.ProjectFilePath, Config.OutputFilePath);

            return new FileItem[] { FileItem.GetItemByPath(Config.OutputFilePath) };
        }
예제 #20
0
        /** Sets up the environment for linking this module. */
        public virtual void SetupPrivateLinkEnvironment(
            ref LinkEnvironment LinkEnvironment,
            ref List<STBuildBinary> BinaryDependencies,
            ref Dictionary<STBuildModule, bool> VisitedModules
            )
        {
            // Allow the module's public dependencies to add library paths and additional libraries to the link environment.
            SetupPublicLinkEnvironment(Binary, ref LinkEnvironment.Config.LibraryPaths, ref LinkEnvironment.Config.AdditionalLibraries, ref LinkEnvironment.Config.Frameworks, ref LinkEnvironment.Config.WeakFrameworks,
                ref LinkEnvironment.Config.AdditionalFrameworks, ref LinkEnvironment.Config.AdditionalShadowFiles, ref LinkEnvironment.Config.AdditionalBundleResources, ref LinkEnvironment.Config.DelayLoadDLLs, ref BinaryDependencies, ref 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(Binary, ref LinkEnvironment.Config.LibraryPaths, ref LinkEnvironment.Config.AdditionalLibraries, ref LinkEnvironment.Config.Frameworks, ref LinkEnvironment.Config.WeakFrameworks,
                    ref LinkEnvironment.Config.AdditionalFrameworks, ref LinkEnvironment.Config.AdditionalShadowFiles, ref LinkEnvironment.Config.AdditionalBundleResources, ref LinkEnvironment.Config.DelayLoadDLLs, ref BinaryDependencies, ref VisitedModules);
            }
        }