/// <summary>
        /// Creates the cache object
        /// </summary>
        /// <param name="Target">The target to create the cache for</param>
        /// <returns>The new instance</returns>
        public static FlatCPPIncludeDependencyCache Create(STBuildTarget Target)
        {
            string CachePath = FlatCPPIncludeDependencyCache.GetDependencyCachePathForTarget(Target); ;

            // See whether the cache file exists.
            FileItem Cache = FileItem.GetItemByPath(CachePath);
            if (Cache.bExists)
            {
                if (BuildConfiguration.bPrintPerformanceInfo)
                {
                    Log.TraceInformation("Loading existing FlatCPPIncludeDependencyCache: " + Cache.AbsolutePath);
                }

                var TimerStartTime = DateTime.UtcNow;

                // Deserialize cache from disk if there is one.
                FlatCPPIncludeDependencyCache Result = Load(Cache);
                if (Result != null)
                {
                    var TimerDuration = DateTime.UtcNow - TimerStartTime;
                    if (BuildConfiguration.bPrintPerformanceInfo)
                    {
                        Log.TraceInformation("Loading FlatCPPIncludeDependencyCache took " + TimerDuration.TotalSeconds + "s");
                    }
                    return Result;
                }
            }

            // Fall back to a clean cache on error or non-existence.
            return new FlatCPPIncludeDependencyCache(Cache);
        }
Exemple #2
0
        /// <summary>
        /// Creates a precompiled header action to generate a new pch file 
        /// </summary>
        /// <param name="PCHHeaderNameInCode">The precompiled header name as it appeared in an #include statement</param>
        /// <param name="PrecompiledHeaderIncludeFilename">Name of the header used for pch.</param>
        /// <param name="ProjectCPPEnvironment">The environment the C/C++ files in the project are compiled with.</param>
        /// <param name="OutputDirectory">The folder to save the generated PCH file to</param>
        /// <param name="ModuleName">Name of the module this PCH is being generated for</param>
        /// <param name="bAllowDLLExports">True if we should allow DLLEXPORT definitions for this PCH</param>
        /// <returns>the compilation output result of the created pch.</returns>
        public static CPPOutput GeneratePCHCreationAction(STBuildTarget Target, string PCHHeaderNameInCode, FileItem PrecompiledHeaderIncludeFilename, CPPEnvironment ProjectCPPEnvironment, string OutputDirectory, string ModuleName, bool bAllowDLLExports)
        {
            // Find the header file to be precompiled. Don't skip external headers
            if (PrecompiledHeaderIncludeFilename.bExists)
            {
                // Create a Dummy wrapper around the PCH to avoid problems with #pragma once on clang
                var ToolChain = STToolChain.GetPlatformToolChain(ProjectCPPEnvironment.Config.Target.Platform);
                string PCHGuardDefine = Path.GetFileNameWithoutExtension(PrecompiledHeaderIncludeFilename.AbsolutePath).ToUpper();
                string LocalPCHHeaderNameInCode = ToolChain.ConvertPath(PrecompiledHeaderIncludeFilename.AbsolutePath);
                string TmpPCHHeaderContents = String.Format("#ifndef __AUTO_{0}_H__\n#define __AUTO_{0}_H__\n//Last Write: {2}\n#include \"{1}\"\n#endif//__AUTO_{0}_H__", PCHGuardDefine, LocalPCHHeaderNameInCode, PrecompiledHeaderIncludeFilename.LastWriteTime);
                string DummyPath = Path.Combine(
                    ProjectCPPEnvironment.Config.OutputDirectory,
                    Path.GetFileName(PrecompiledHeaderIncludeFilename.AbsolutePath));
                FileItem DummyPCH = FileItem.CreateIntermediateTextFile(DummyPath, TmpPCHHeaderContents);

                // Create a new C++ environment that is used to create the PCH.
                var ProjectPCHEnvironment = ProjectCPPEnvironment.DeepCopy();
                ProjectPCHEnvironment.Config.PrecompiledHeaderAction = PrecompiledHeaderAction.Create;
                ProjectPCHEnvironment.Config.PrecompiledHeaderIncludeFilename = PrecompiledHeaderIncludeFilename.AbsolutePath;
                ProjectPCHEnvironment.Config.PCHHeaderNameInCode = PCHHeaderNameInCode;
                ProjectPCHEnvironment.Config.OutputDirectory = OutputDirectory;

                if (!bAllowDLLExports)
                {
                    for (var CurDefinitionIndex = 0; CurDefinitionIndex < ProjectPCHEnvironment.Config.Definitions.Count; ++CurDefinitionIndex)
                    {
                        // We change DLLEXPORT to DLLIMPORT for "shared" PCH headers
                        var OldDefinition = ProjectPCHEnvironment.Config.Definitions[CurDefinitionIndex];
                        if (OldDefinition.EndsWith("=DLLEXPORT"))
                        {
                            ProjectPCHEnvironment.Config.Definitions[CurDefinitionIndex] = OldDefinition.Replace("DLLEXPORT", "DLLIMPORT");
                        }
                    }
                }

                // Cache our CPP environment so that we can check for outdatedness quickly.  Only files that have includes need this.
                DummyPCH.CachedCPPIncludeInfo = ProjectPCHEnvironment.Config.CPPIncludeInfo;

                Log.TraceVerbose("Found PCH file \"{0}\".", PrecompiledHeaderIncludeFilename);

                // Create the action to compile the PCH file.
                return ProjectPCHEnvironment.CompileFiles(Target, new List<FileItem>() { DummyPCH }, ModuleName);
            }
            throw new BuildException("Couldn't find PCH file \"{0}\".", PrecompiledHeaderIncludeFilename);
        }
Exemple #3
0
 /// <summary>
 /// Generates a full path to action history file for the specified target.
 /// </summary>
 public static string GeneratePathForTarget(STBuildTarget Target)
 {
     string Folder = null;
     if (Target.ShouldCompileMonolithic() || Target.TargetType == TargetRules.TargetType.Program)
     {
         // Monolithic configs and programs have their Action History stored in their respective project folders
         // or under engine intermediate folder + program name folder
         string RootDirectory = STBuildTool.GetUProjectPath();
         if (String.IsNullOrEmpty(RootDirectory))
         {
             RootDirectory = Path.GetFullPath(BuildConfiguration.RelativeEnginePath);
         }
         Folder = Path.Combine(RootDirectory, BuildConfiguration.PlatformIntermediateFolder, Target.GetTargetName());
     }
     else
     {
         // Shared action history (unless this is a rocket target)
         Folder = STBuildTool.RunningRocket() ?
             Path.Combine(STBuildTool.GetUProjectPath(), BuildConfiguration.BaseIntermediateFolder) :
             BuildConfiguration.BaseIntermediatePath;
     }
     return Path.Combine(Folder, "ActionHistory.bin").Replace("\\", "/");
 }
        public string TargetName; // Name of the target currently being compiled

        #endregion Fields

        #region Constructors

        public SHTManifest(STBuildTarget Target, string InRootLocalPath, string InRootBuildPath, IEnumerable<SHTModuleInfo> ModuleInfo)
        {
            IsGameTarget = TargetRules.IsGameType(Target.TargetType);
            RootLocalPath = InRootLocalPath;
            RootBuildPath = InRootBuildPath;
            TargetName = Target.GetTargetName();

            Modules = ModuleInfo.Select(Info => new Module
            {
                Name = Info.ModuleName,
                ModuleType = Info.ModuleType,
                BaseDirectory = Info.ModuleDirectory,
                IncludeBase = Info.ModuleDirectory,
                OutputDirectory = Path.GetDirectoryName(Info.GeneratedCPPFilenameBase),
                ClassesHeaders = Info.PublicUObjectClassesHeaders.Select((Header) => Header.AbsolutePath).ToList(),
                PublicHeaders = Info.PublicUObjectHeaders.Select((Header) => Header.AbsolutePath).ToList(),
                PrivateHeaders = Info.PrivateUObjectHeaders.Select((Header) => Header.AbsolutePath).ToList(),
                PCH = Info.PCH,
                GeneratedCPPFilenameBase = Info.GeneratedCPPFilenameBase,
                //@todo.Rocket: This assumes Engine/Source is a 'safe' folder name to check for
                SaveExportedHeaders = !STBuildTool.RunningRocket() || !Info.ModuleDirectory.Contains("Engine\\Source\\")

            }).ToList();
        }
Exemple #5
0
 /// <summary>
 /// Create an instance initialized to the given configuration
 /// </summary>
 /// <param name="InConfig">The build binary configuration to initialize the instance to</param>
 public STBuildBinaryCSDLL(STBuildTarget InTarget, STBuildBinaryConfiguration InConfig)
     : base(InTarget, InConfig)
 {
 }
Exemple #6
0
 public STBuildBinaryCPP(STBuildTarget InTarget, STBuildBinaryConfiguration InConfig)
     : base(InTarget, InConfig)
 {
     ModuleNames = new HashSet<string>(InConfig.ModuleNames);
     bCreateImportLibrarySeparately = InConfig.bCreateImportLibrarySeparately;
     bIncludeDependentLibrariesInLibrary = InConfig.bIncludeDependentLibrariesInLibrary;
 }
Exemple #7
0
 public virtual void PostBuildSync(STBuildTarget Target)
 {
 }
Exemple #8
0
 public virtual CPPOutput CompileRCFiles(STBuildTarget Target, CPPEnvironment Environment, List<FileItem> RCFiles)
 {
     CPPOutput Result = new CPPOutput();
     return Result;
 }
Exemple #9
0
 /**
  * Recursively adds modules that are referenced only for include paths (not actual dependencies).
  *
  * @param	Target	The target we are currently building
  * @param	bPublicIncludesOnly	True to only add modules for public includes, false to add all include path modules.  Regardless of what you pass here, recursive adds will only add public include path modules.
  */
 public virtual void RecursivelyAddIncludePathModules(STBuildTarget Target, bool bPublicIncludesOnly)
 {
 }
Exemple #10
0
        public override CPPOutput CompileCPPFiles(STBuildTarget Target, CPPEnvironment CompileEnvironment, List<FileItem> SourceFiles, string ModuleName)
        {
            var EnvVars = VCEnvironment.SetEnvironment(CompileEnvironment.Config.Target.Platform);

            StringBuilder Arguments = new StringBuilder();
            AppendCLArguments_Global(CompileEnvironment, EnvVars, Arguments);

            // Add include paths to the argument list.
            if (!BuildConfiguration.bRunUnrealCodeAnalyzer)
            {
                foreach (string IncludePath in CompileEnvironment.Config.CPPIncludeInfo.IncludePaths)
                {
                    Arguments.AppendFormat(" /I \"{0}\"", IncludePath);
                }
            }
            else
            {
                foreach (string IncludePath in CompileEnvironment.Config.CPPIncludeInfo.IncludePaths)
                {
                    Arguments.AppendFormat(" /I \"{0}\"", System.IO.Path.GetFullPath(IncludePath));
                }
            }
            foreach (string IncludePath in CompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths)
            {
                if (WindowsPlatform.bCompileWithClang)
                {
                    // @todo Clang: Clang uses a special command-line syntax for system headers.  This is used for two reasons.  The first is that Clang will automatically
                    // suppress compiler warnings in headers found in these directories, such as the DirectX SDK headers.  The other reason this is important is in the case
                    // where there the same header include path is passed as both a regular include path and a system include path (extracted from INCLUDE environment).  In
                    // this case Clang will ignore any earlier occurrence of the include path, preventing a system header include path from overriding a different system
                    // include path set later on by a module.  NOTE: When passing "-Xclang", these options will always appear at the end of the command-line string, meaning
                    // they will be forced to appear *after* all environment-variable-extracted includes.  This is technically okay though.
                    Arguments.AppendFormat(" -Xclang -internal-isystem -Xclang \"{0}\"", IncludePath);
                }
                else
                {
                    Arguments.AppendFormat(" /I \"{0}\"", IncludePath);
                }
            }

            if (CompileEnvironment.Config.CLRMode == CPPCLRMode.CLREnabled)
            {
                // Add .NET framework assembly paths.  This is needed so that C++/CLI projects
                // can reference assemblies with #using, without having to hard code a path in the
                // .cpp file to the assembly's location.
                foreach (string AssemblyPath in CompileEnvironment.Config.SystemDotNetAssemblyPaths)
                {
                    Arguments.AppendFormat(" /AI \"{0}\"", AssemblyPath);
                }

                // Add explicit .NET framework assembly references
                foreach (string AssemblyName in CompileEnvironment.Config.FrameworkAssemblyDependencies)
                {
                    Arguments.AppendFormat(" /FU \"{0}\"", AssemblyName);
                }

                // Add private assembly references
                foreach (PrivateAssemblyInfo CurAssemblyInfo in CompileEnvironment.PrivateAssemblyDependencies)
                {
                    Arguments.AppendFormat(" /FU \"{0}\"", CurAssemblyInfo.FileItem.AbsolutePath);
                }
            }

            // Add preprocessor definitions to the argument list.
            foreach (string Definition in CompileEnvironment.Config.Definitions)
            {
                // Escape all quotation marks so that they get properly passed with the command line.
                var DefinitionArgument = Definition.Contains("\"") ? Definition.Replace("\"", "\\\"") : Definition;
                Arguments.AppendFormat(" /D \"{0}\"", DefinitionArgument);
            }

            var BuildPlatform = STBuildPlatform.GetBuildPlatformForCPPTargetPlatform(CompileEnvironment.Config.Target.Platform);

            // Create a compile action for each source file.
            CPPOutput Result = new CPPOutput();
            foreach (FileItem SourceFile in SourceFiles)
            {
                Action CompileAction = new Action(ActionType.Compile);
                CompileAction.CommandDescription = "Compile";

                StringBuilder FileArguments = new StringBuilder();
                bool bIsPlainCFile = Path.GetExtension(SourceFile.AbsolutePath).ToUpperInvariant() == ".C";

                // Add the C++ source file and its included files to the prerequisite item list.
                AddPrerequisiteSourceFile(Target, BuildPlatform, CompileEnvironment, SourceFile, CompileAction.PrerequisiteItems);

                // If this is a CLR file then make sure our dependent assemblies are added as prerequisites
                if (CompileEnvironment.Config.CLRMode == CPPCLRMode.CLREnabled)
                {
                    foreach (PrivateAssemblyInfo CurPrivateAssemblyDependency in CompileEnvironment.PrivateAssemblyDependencies)
                    {
                        CompileAction.PrerequisiteItems.Add(CurPrivateAssemblyDependency.FileItem);
                    }
                }

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

                bool bEmitsObjectFile = true;
                if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Create)
                {
                    // Generate a CPP File that just includes the precompiled header.
                    string PCHCPPFilename = "PCH." + ModuleName + "." + Path.GetFileName(CompileEnvironment.Config.PrecompiledHeaderIncludeFilename) + ".cpp";
                    string PCHCPPPath = Path.Combine(CompileEnvironment.Config.OutputDirectory, PCHCPPFilename);
                    FileItem PCHCPPFile = FileItem.CreateIntermediateTextFile(
                        PCHCPPPath,
                        string.Format("#include \"{0}\"\r\n", CompileEnvironment.Config.PrecompiledHeaderIncludeFilename)
                        );

                    // Make sure the original source directory the PCH header file existed in is added as an include
                    // path -- it might be a private PCH header and we need to make sure that its found!
                    string OriginalPCHHeaderDirectory = Path.GetDirectoryName(SourceFile.AbsolutePath);
                    FileArguments.AppendFormat(" /I \"{0}\"", OriginalPCHHeaderDirectory);

                    var PrecompiledFileExtension = STBuildPlatform.BuildPlatformDictionary[STTargetPlatform.Win64].GetBinaryExtension(STBuildBinaryType.PrecompiledHeader);
                    // Add the precompiled header file to the produced items list.
                    FileItem PrecompiledHeaderFile = FileItem.GetItemByPath(
                        Path.Combine(
                            CompileEnvironment.Config.OutputDirectory,
                        Path.GetFileName(SourceFile.AbsolutePath) + PrecompiledFileExtension
                            )
                        );
                    CompileAction.ProducedItems.Add(PrecompiledHeaderFile);
                    Result.PrecompiledHeaderFile = PrecompiledHeaderFile;

                    // @todo clang: Ideally clang-cl would support the regular MSVC arguments for PCH files, and we wouldn't need to do this manually
                    if (WindowsPlatform.bCompileWithClang)
                    {
                        // Tell Clang to generate a PCH header
                        FileArguments.Append(" -Xclang -x -Xclang c++-header");	// @todo clang: Doesn't work due to Clang-cl overriding us at the end of the command-line (see -### option output)
                        FileArguments.AppendFormat(" /Fo\"{0}\"", PrecompiledHeaderFile.AbsolutePath);

                        // Clang PCH generation doesn't create an .obj file to link in, unlike MSVC
                        bEmitsObjectFile = false;
                    }
                    else
                    {
                        // Add the parameters needed to compile the precompiled header file to the command-line.
                        FileArguments.AppendFormat(" /Yc\"{0}\"", CompileEnvironment.Config.PrecompiledHeaderIncludeFilename);
                        FileArguments.AppendFormat(" /Fp\"{0}\"", PrecompiledHeaderFile.AbsolutePath);

                        // If we're creating a PCH that will be used to compile source files for a library, we need
                        // the compiled modules to retain a reference to PCH's module, so that debugging information
                        // will be included in the library.  This is also required to avoid linker warning "LNK4206"
                        // when linking an application that uses this library.
                        if (CompileEnvironment.Config.bIsBuildingLibrary)
                        {
                            // NOTE: The symbol name we use here is arbitrary, and all that matters is that it is
                            // unique per PCH module used in our library
                            string FakeUniquePCHSymbolName = Path.GetFileNameWithoutExtension(CompileEnvironment.Config.PrecompiledHeaderIncludeFilename);
                            FileArguments.AppendFormat(" /Yl{0}", FakeUniquePCHSymbolName);
                        }
                    }

                    FileArguments.AppendFormat(" \"{0}\"", PCHCPPFile.AbsolutePath);

                    CompileAction.StatusDescription = PCHCPPFilename;
                }
                else
                {
                    if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Include)
                    {
                        CompileAction.bIsUsingPCH = true;
                        CompileAction.PrerequisiteItems.Add(CompileEnvironment.PrecompiledHeaderFile);

                        if (WindowsPlatform.bCompileWithClang)
                        {
                            // NOTE: With Clang, PCH headers are ALWAYS forcibly included!
                            // NOTE: This needs to be before the other include paths to ensure Clang uses it instead of the source header file.
                            FileArguments.AppendFormat(" /FI\"{0}\"", Path.ChangeExtension(CompileEnvironment.PrecompiledHeaderFile.AbsolutePath, null));
                        }
                        else
                        {
                            FileArguments.AppendFormat(" /Yu\"{0}\"", CompileEnvironment.Config.PCHHeaderNameInCode);
                            FileArguments.AppendFormat(" /Fp\"{0}\"", CompileEnvironment.PrecompiledHeaderFile.AbsolutePath);

                            // Is it unsafe to always force inclusion?  Clang is doing it, and .generated.cpp files
                            // won't work otherwise, because they're not located in the context of the module,
                            // so they can't access the module's PCH without an absolute path.
                            //if( CompileEnvironment.Config.bForceIncludePrecompiledHeader )
                            {
                                // Force include the precompiled header file.  This is needed because we may have selected a
                                // precompiled header that is different than the first direct include in the C++ source file, but
                                // we still need to make sure that our precompiled header is the first thing included!
                                FileArguments.AppendFormat(" /FI\"{0}\"", CompileEnvironment.Config.PCHHeaderNameInCode);
                            }
                        }
                    }

                    // UnrealCodeAnalyzer requires compiled file name to be first argument.
                    if (!BuildConfiguration.bRunUnrealCodeAnalyzer)
                    {
                        // Add the source file path to the command-line.
                        FileArguments.AppendFormat(" \"{0}\"", SourceFile.AbsolutePath);
                    }

                    CompileAction.StatusDescription = Path.GetFileName(SourceFile.AbsolutePath);
                }

                if (bEmitsObjectFile)
                {
                    var ObjectFileExtension = STBuildPlatform.BuildPlatformDictionary[STTargetPlatform.Win64].GetBinaryExtension(STBuildBinaryType.Object);
                    // Add the object file to the produced item list.
                    FileItem ObjectFile = FileItem.GetItemByPath(
                        Path.Combine(
                            CompileEnvironment.Config.OutputDirectory,
                            Path.GetFileName(SourceFile.AbsolutePath) + ObjectFileExtension
                            )
                        );
                    CompileAction.ProducedItems.Add(ObjectFile);
                    Result.ObjectFiles.Add(ObjectFile);
                    // UnrealCodeAnalyzer requires specific position of output file.
                    if (!BuildConfiguration.bRunUnrealCodeAnalyzer)
                    {
                        FileArguments.AppendFormat(" /Fo\"{0}\"", ObjectFile.AbsolutePath);
                    }
                }

                // Create PDB files if we were configured to do that.
                //
                // Also, when debug info is off and XGE is enabled, force PDBs, otherwise it will try to share
                // a PDB file, which causes PCH creation to be serial rather than parallel (when debug info is disabled)
                //		--> See https://udn.epicgames.com/lists/showpost.php?id=50619&list=unprog3
                if (BuildConfiguration.bUsePDBFiles ||
                    (BuildConfiguration.bAllowXGE && !CompileEnvironment.Config.bCreateDebugInfo))
                {
                    string PDBFileName;
                    bool bActionProducesPDB = false;

                    // All files using the same PCH are required to share the same PDB that was used when compiling the PCH
                    if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Include)
                    {
                        PDBFileName = "PCH." + ModuleName + "." + Path.GetFileName(CompileEnvironment.Config.PrecompiledHeaderIncludeFilename);
                    }
                    // Files creating a PCH use a PDB per file.
                    else if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Create)
                    {
                        PDBFileName = "PCH." + ModuleName + "." + Path.GetFileName(CompileEnvironment.Config.PrecompiledHeaderIncludeFilename);
                        bActionProducesPDB = true;
                    }
                    // Ungrouped C++ files use a PDB per file.
                    else if (!bIsPlainCFile)
                    {
                        PDBFileName = Path.GetFileName(SourceFile.AbsolutePath);
                        bActionProducesPDB = true;
                    }
                    // Group all plain C files that doesn't use PCH into the same PDB
                    else
                    {
                        PDBFileName = "MiscPlainC";
                    }

                    {
                        // Specify the PDB file that the compiler should write to.
                        FileItem PDBFile = FileItem.GetItemByPath(
                                Path.Combine(
                                    CompileEnvironment.Config.OutputDirectory,
                                    PDBFileName + ".pdb"
                                    )
                                );
                        FileArguments.AppendFormat(" /Fd\"{0}\"", PDBFile.AbsolutePath);

                        // Only use the PDB as an output file if we want PDBs and this particular action is
                        // the one that produces the PDB (as opposed to no debug info, where the above code
                        // is needed, but not the output PDB, or when multiple files share a single PDB, so
                        // only the action that generates it should count it as output directly)
                        if (BuildConfiguration.bUsePDBFiles && bActionProducesPDB)
                        {
                            CompileAction.ProducedItems.Add(PDBFile);
                            Result.DebugDataFiles.Add(PDBFile);
                        }
                    }
                }

                // Add C or C++ specific compiler arguments.
                if (bIsPlainCFile)
                {
                    AppendCLArguments_C(FileArguments);
                }
                else
                {
                    AppendCLArguments_CPP(CompileEnvironment, FileArguments);
                }

                CompileAction.WorkingDirectory = Path.GetFullPath(".");
                if (BuildConfiguration.bRunUnrealCodeAnalyzer)
                {
                    CompileAction.CommandPath = System.IO.Path.Combine(CompileAction.WorkingDirectory, @"..", @"Binaries", @"Win32", @"UnrealCodeAnalyzer.exe");
                }
                else
                {
                    CompileAction.CommandPath = EnvVars.CompilerPath;
                }

                if (!WindowsPlatform.bCompileWithClang || !BuildConfiguration.bRunUnrealCodeAnalyzer)
                {
                    CompileAction.bIsVCCompiler = true;
                }

                string UnrealCodeAnalyzerArguments = "";
                if (BuildConfiguration.bRunUnrealCodeAnalyzer)
                {
                    var ObjectFileExtension = @".includes";
                    FileItem ObjectFile = FileItem.GetItemByPath(Path.Combine(CompileEnvironment.Config.OutputDirectory, Path.GetFileName(SourceFile.AbsolutePath) + ObjectFileExtension));
                    var ClangPath = System.IO.Path.Combine(CompileAction.WorkingDirectory, @"ThirdParty", @"llvm", @"3.5.0", @"bin", @"vs2013", @"x86", @"release", @"clang++.exe");
                    UnrealCodeAnalyzerArguments = @"-CreateIncludeFiles " + SourceFile.AbsolutePath + @" -OutputFile=""" + ObjectFile.AbsolutePath + @""" -- " + ClangPath + @" --driver-mode=cl ";
                }

                CompileAction.CommandArguments = UnrealCodeAnalyzerArguments + Arguments.ToString() + FileArguments.ToString() + CompileEnvironment.Config.AdditionalArguments;

                if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Create)
                {
                    Log.TraceVerbose("Creating PCH: " + CompileEnvironment.Config.PrecompiledHeaderIncludeFilename);
                    Log.TraceVerbose("     Command: " + CompileAction.CommandArguments);
                }
                else
                {
                    Log.TraceVerbose("   Compiling: " + CompileAction.StatusDescription);
                    Log.TraceVerbose("     Command: " + CompileAction.CommandArguments);
                }

                if (WindowsPlatform.bCompileWithClang || BuildConfiguration.bRunUnrealCodeAnalyzer)
                {
                    // Clang doesn't print the file names by default, so we'll do it ourselves
                    CompileAction.bShouldOutputStatusDescription = true;
                }
                else
                {
                    // VC++ always outputs the source file name being compiled, so we don't need to emit this ourselves
                    CompileAction.bShouldOutputStatusDescription = false;
                }

                // Don't farm out creation of precompiled headers as it is the critical path task.
                CompileAction.bCanExecuteRemotely =
                    CompileEnvironment.Config.PrecompiledHeaderAction != PrecompiledHeaderAction.Create ||
                    BuildConfiguration.bAllowRemotelyCompiledPCHs
                    ;

                // @todo: XGE has problems remote compiling C++/CLI files that use .NET Framework 4.0
                if (CompileEnvironment.Config.CLRMode == CPPCLRMode.CLREnabled)
                {
                    CompileAction.bCanExecuteRemotely = false;
                }
            }
            return Result;
        }
Exemple #11
0
        public override CPPOutput CompileRCFiles(STBuildTarget Target, CPPEnvironment Environment, List<FileItem> RCFiles)
        {
            var EnvVars = VCEnvironment.SetEnvironment(Environment.Config.Target.Platform);

            CPPOutput Result = new CPPOutput();

            var BuildPlatform = STBuildPlatform.GetBuildPlatformForCPPTargetPlatform(Environment.Config.Target.Platform);

            foreach (FileItem RCFile in RCFiles)
            {
                Action CompileAction = new Action(ActionType.Compile);
                CompileAction.CommandDescription = "Resource";
                CompileAction.WorkingDirectory = Path.GetFullPath(".");
                CompileAction.CommandPath = EnvVars.ResourceCompilerPath;
                CompileAction.StatusDescription = Path.GetFileName(RCFile.AbsolutePath);

                // Resource tool can run remotely if possible
                CompileAction.bCanExecuteRemotely = true;

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

                // Suppress header spew
                CompileAction.CommandArguments += " /nologo";

                // If we're compiling for 64-bit Windows, also add the _WIN64 definition to the resource
                // compiler so that we can switch on that in the .rc file using #ifdef.
                if (Environment.Config.Target.Platform == CPPTargetPlatform.Win64)
                {
                    CompileAction.CommandArguments += " /D _WIN64";
                }

                // When targeting Windows XP with Visual Studio 2012+, we need to tell the compiler to use the older Windows SDK that works
                // with Windows XP (http://blogs.msdn.com/b/vcblog/archive/2012/10/08/10357555.aspx)
                if (WindowsPlatform.IsWindowsXPSupported())
                {
                    CompileAction.CommandArguments += " /D_USING_V110_SDK71_";
                }

                // Language
                CompileAction.CommandArguments += " /l 0x409";

                // Include paths.
                foreach (string IncludePath in Environment.Config.CPPIncludeInfo.IncludePaths)
                {
                    CompileAction.CommandArguments += string.Format(" /i \"{0}\"", IncludePath);
                }

                // System include paths.
                foreach (var SystemIncludePath in Environment.Config.CPPIncludeInfo.SystemIncludePaths)
                {
                    CompileAction.CommandArguments += string.Format(" /i \"{0}\"", SystemIncludePath);
                }

                // Preprocessor definitions.
                foreach (string Definition in Environment.Config.Definitions)
                {
                    CompileAction.CommandArguments += string.Format(" /d \"{0}\"", Definition);
                }

                // Add the RES file to the produced item list.
                FileItem CompiledResourceFile = FileItem.GetItemByPath(
                    Path.Combine(
                        Environment.Config.OutputDirectory,
                        Path.GetFileName(RCFile.AbsolutePath) + ".res"
                        )
                    );
                CompileAction.ProducedItems.Add(CompiledResourceFile);
                CompileAction.CommandArguments += string.Format(" /fo \"{0}\"", CompiledResourceFile.AbsolutePath);
                Result.ObjectFiles.Add(CompiledResourceFile);

                // Add the RC file as a prerequisite of the action.
                CompileAction.CommandArguments += string.Format(" \"{0}\"", RCFile.AbsolutePath);

                // Add the C++ source file and its included files to the prerequisite item list.
                AddPrerequisiteSourceFile(Target, BuildPlatform, Environment, RCFile, CompileAction.PrerequisiteItems);
            }

            return Result;
        }
Exemple #12
0
        public override void PostBuildSync(STBuildTarget Target)
        {
            base.PostBuildSync(Target);

            string AppName = Target.TargetType == TargetRules.TargetType.Game ? Target.GameName : Target.AppName;

            if (BuildHostPlatform.Current.Platform == STTargetPlatform.Mac)
            {
                string RemoteShadowDirectoryMac = Path.GetDirectoryName(Target.OutputPath);
                string FinalRemoteExecutablePath = String.Format("{0}/Payload/{1}.app/{1}", RemoteShadowDirectoryMac, Target.GameName);

                // strip the debug info from the executable if needed
                if (BuildConfiguration.bStripSymbolsOnIOS || (Target.Configuration == STTargetConfiguration.Shipping) || STBuildTool.BuildingRocket())
                {
                    Process StripProcess = new Process();
                    StripProcess.StartInfo.WorkingDirectory = RemoteShadowDirectoryMac;
                    StripProcess.StartInfo.FileName = "/usr/bin/xcrun";
                    StripProcess.StartInfo.Arguments = "strip \"" + Target.OutputPath + "\"";
                    StripProcess.OutputDataReceived += new DataReceivedEventHandler(OutputReceivedDataEventHandler);
                    StripProcess.ErrorDataReceived += new DataReceivedEventHandler(OutputReceivedDataEventHandler);

                    OutputReceivedDataEventHandlerEncounteredError = false;
                    OutputReceivedDataEventHandlerEncounteredErrorMessage = "";
                    Utils.RunLocalProcess(StripProcess);
                    if (OutputReceivedDataEventHandlerEncounteredError)
                    {
                        throw new Exception(OutputReceivedDataEventHandlerEncounteredErrorMessage);
                    }
                }

                // copy the executable
                if (!File.Exists(FinalRemoteExecutablePath))
                {
                    Directory.CreateDirectory(String.Format("{0}/Payload/{1}.app", RemoteShadowDirectoryMac, Target.GameName));
                }
                File.Copy(Target.OutputPath, FinalRemoteExecutablePath, true);

                if (BuildConfiguration.bCreateStubIPA)
                {
                    string Project = Target.ProjectDirectory + "/" + Target.GameName + ".uproject";

                    // generate the dummy project so signing works
                    if (Target.GameName == "UE4Game" || Target.GameName == "UE4Client" || Utils.IsFileUnderDirectory(Target.ProjectDirectory + "/" + Target.GameName + ".uproject", Path.GetFullPath("../..")))
                    {
                        STBuildTool.GenerateProjectFiles (new XcodeProjectFileGenerator (), new string[] {"-platforms=IOS", "-NoIntellIsense", "-iosdeployonly", "-ignorejunk"});
                        Project = Path.GetFullPath("../..") + "/UE4_IOS.xcodeproj";
                    }
                    else
                    {
                        Project = Target.ProjectDirectory + "/" + Target.GameName + ".xcodeproj";
                    }

                    if (Directory.Exists (Project))
                    {
                        // ensure the plist, entitlements, and provision files are properly copied
                        var DeployHandler = STBuildDeploy.GetBuildDeploy(Target.Platform);
                        if (DeployHandler != null)
                        {
                            DeployHandler.PrepTargetForDeployment(Target);
                        }

                        // code sign the project
                        string CmdLine = XcodeDeveloperDir + "usr/bin/xcodebuild" +
                                        " -project \"" + Project + "\"" +
                                        " -configuration " + Target.Configuration +
                                        " -scheme '" + Target.GameName + " - iOS'" +
                                        " -sdk iphoneos" +
                                        " CODE_SIGN_IDENTITY=\"iPhone Developer\"";

                        Console.WriteLine("Code signing with command line: " + CmdLine);

                        Process SignProcess = new Process ();
                        SignProcess.StartInfo.WorkingDirectory = RemoteShadowDirectoryMac;
                        SignProcess.StartInfo.FileName = "/usr/bin/xcrun";
                        SignProcess.StartInfo.Arguments = CmdLine;
                        SignProcess.OutputDataReceived += new DataReceivedEventHandler (OutputReceivedDataEventHandler);
                        SignProcess.ErrorDataReceived += new DataReceivedEventHandler (OutputReceivedDataEventHandler);

                        OutputReceivedDataEventHandlerEncounteredError = false;
                        OutputReceivedDataEventHandlerEncounteredErrorMessage = "";
                        Utils.RunLocalProcess (SignProcess);

                        // delete the temp project
                        if (Project.Contains ("_IOS.xcodeproj"))
                        {
                            Directory.Delete (Project, true);
                        }

                        if (OutputReceivedDataEventHandlerEncounteredError)
                        {
                            throw new Exception (OutputReceivedDataEventHandlerEncounteredErrorMessage);
                        }

                        // Package the stub
                        PackageStub (RemoteShadowDirectoryMac, Target.GameName, Path.GetFileNameWithoutExtension (Target.OutputPath));
                    }
                }

                {
                    // Copy bundled assets from additional frameworks to the intermediate assets directory (so they can get picked up during staging)
                    String LocalFrameworkAssets = Path.GetFullPath( Target.ProjectDirectory + "/Intermediate/IOS/FrameworkAssets" );

                    // Clean the local dest directory if it exists
                    CleanIntermediateDirectory( LocalFrameworkAssets );

                    foreach ( STBuildFramework Framework in RememberedAdditionalFrameworks )
                    {
                        if ( Framework.OwningModule == null || Framework.CopyBundledAssets == null || Framework.CopyBundledAssets == "" )
                        {
                            continue;		// Only care if we need to copy bundle assets
                        }

                        if ( Framework.OwningModule.Target != Target )
                        {
                            continue;		// This framework item doesn't belong to this target, skip it
                        }

                        string LocalZipPath = GetLocalFrameworkZipPath( Framework );

                        LocalZipPath = LocalZipPath.Replace( ".zip", "" );

                        // For now, this is hard coded, but we need to loop over all modules, and copy bundled assets that need it
                        string LocalSource	= LocalZipPath + "/" + Framework.CopyBundledAssets;
                        string BundleName	= Framework.CopyBundledAssets.Substring( Framework.CopyBundledAssets.LastIndexOf( '/' ) + 1 );
                        string LocalDest	= LocalFrameworkAssets + "/" + BundleName;

                        Log.TraceInformation( "Copying bundled asset... LocalSource: {0}, LocalDest: {1}", LocalSource, LocalDest );

                        string ResultsText;
                        RunExecutableAndWait( "cp", String.Format( "-R -L {0} {1}", LocalSource.Replace(" ", "\\ "), LocalDest.Replace(" ", "\\ ") ), out ResultsText );
                    }
                }
            }
            else
            {
                // store off the binaries
                foreach (STBuildBinary Binary in Target.AppBinaries)
                {
                    BuiltBinaries.Add(Path.GetFullPath(Binary.ToString()));
                }

                // Generate static libraries for monolithic games in Rocket
                if ((STBuildTool.BuildingRocket() || STBuildTool.RunningRocket()) && TargetRules.IsAGame(Target.TargetType))
                {
                    List<STBuildModule> Modules = Target.AppBinaries[0].GetAllDependencyModules(true, false);
                    foreach (STBuildModuleCPP Module in Modules.OfType<STBuildModuleCPP>())
                    {
                        if (Utils.IsFileUnderDirectory(Module.ModuleDirectory, BuildConfiguration.RelativeEnginePath) && Module.Binary == Target.AppBinaries[0])
                        {
                            if (Module.bBuildingRedistStaticLibrary)
                            {
                                foreach (var LibraryPath in Module.RedistStaticLibraryPaths)
                                {
                                    BuiltBinaries.Add(Path.GetFullPath(LibraryPath));
                                }
                            }
                        }
                    }
                }

                // check to see if the DangerouslyFast mode is valid (in other words, a build has gone through since a Rebuild/Clean operation)
                string DangerouslyFastValidFile = Path.Combine(Target.GlobalLinkEnvironment.Config.IntermediateDirectory, "DangerouslyFastIsNotDangerous");
                bool bUseDangerouslyFastModeWasRequested = bUseDangerouslyFastMode;
                if (bUseDangerouslyFastMode)
                {
                    if (!File.Exists(DangerouslyFastValidFile))
                    {
                        Log.TraceInformation("Dangeroulsy Fast mode was requested, but a slow mode hasn't completed. Performing slow now...");
                        bUseDangerouslyFastMode = false;
                    }
                }

                foreach (string FilePath in BuiltBinaries)
                {
                    string RemoteExecutablePath = ConvertPath(FilePath);

                    // when going super fast, just copy the executable to the final resting spot
                    if (bUseDangerouslyFastMode)
                    {
                        Log.TraceInformation("==============================================================================");
                        Log.TraceInformation("USING DANGEROUSLY FAST MODE! IF YOU HAVE ANY PROBLEMS, TRY A REBUILD/CLEAN!!!!");
                        Log.TraceInformation("==============================================================================");

                        // copy the executable
                        string RemoteShadowDirectoryMac = ConvertPath(Path.GetDirectoryName(Target.OutputPath));
                        string FinalRemoteExecutablePath = String.Format("{0}/Payload/{1}.app/{1}", RemoteShadowDirectoryMac, Target.GameName);
                        RPCUtilHelper.Command("/", String.Format("cp -f {0} {1}", RemoteExecutablePath, FinalRemoteExecutablePath), "", null);
                    }
                    else if (!Utils.IsRunningOnMono && BuildHostPlatform.Current.Platform != STTargetPlatform.Mac)
                    {
                        RPCUtilHelper.CopyFile(RemoteExecutablePath, FilePath, false);

                        if (BuildConfiguration.bGeneratedSYMFile == true)
                        {
                            string DSYMExt = ".app.dSYM.zip";
                            RPCUtilHelper.CopyFile(RemoteExecutablePath + DSYMExt, FilePath + DSYMExt, false);
                        }
                    }
                }

                // Generate the stub
                if (BuildConfiguration.bCreateStubIPA || bUseDangerouslyFastMode)
                {
                    // ensure the plist, entitlements, and provision files are properly copied
                    var DeployHandler = STBuildDeploy.GetBuildDeploy(Target.Platform);
                    if (DeployHandler != null)
                    {
                        DeployHandler.PrepTargetForDeployment(Target);
                    }

                    if (!bUseDangerouslyFastMode)
                    {
                        // generate the dummy project so signing works
                        STBuildTool.GenerateProjectFiles(new XcodeProjectFileGenerator(), new string[] { "-NoIntellisense", "-iosdeployonly" });
                    }

                    // now that
                    Process StubGenerateProcess = new Process();
                    StubGenerateProcess.StartInfo.WorkingDirectory = Path.GetFullPath("..\\Binaries\\DotNET\\IOS");
                    StubGenerateProcess.StartInfo.FileName = Path.Combine(StubGenerateProcess.StartInfo.WorkingDirectory, "iPhonePackager.exe");

                    string Arguments = "";

                    string PathToApp = RulesCompiler.GetTargetFilename(AppName);

                    // right now, no programs have a Source subdirectory, so assume the PathToApp is directly in the root
                    if (Path.GetDirectoryName(PathToApp).Contains(@"\Engine\Source\Programs"))
                    {
                        PathToApp = Path.GetDirectoryName(PathToApp);
                    }
                    else
                    {
                        Int32 SourceIndex = PathToApp.LastIndexOf(@"\Source");
                        if (SourceIndex != -1)
                        {
                            PathToApp = PathToApp.Substring(0, SourceIndex);
                        }
                        else
                        {
                            throw new BuildException("The target was not in a /Source subdirectory");
                        }
                    }

                    if (bUseDangerouslyFastMode)
                    {
                        // the quickness!
                        Arguments += "DangerouslyFast " + PathToApp;
                    }
                    else
                    {
                        Arguments += "PackageIPA \"" + PathToApp + "\" -createstub";
                        // if we are making the dsym, then we can strip the debug info from the executable
                        if (BuildConfiguration.bStripSymbolsOnIOS || (Target.Configuration == STTargetConfiguration.Shipping))
                        {
                            Arguments += " -strip";
                        }
                    }
                    Arguments += " -config " + Target.Configuration + " -mac " + RemoteServerName;

                    var BuildPlatform = STBuildPlatform.GetBuildPlatform(Target.Platform);
                    string Architecture = BuildPlatform.GetActiveArchitecture();
                    if (Architecture != "")
                    {
                        // pass along the architecture if we need, skipping the initial -, so we have "-architecture simulator"
                        Arguments += " -architecture " + Architecture.Substring(1);
                    }

                    if (!bUseRPCUtil )
                    {
                        Arguments += " -usessh";
                        Arguments += " -sshexe \"" + ResolvedSSHExe + "\"";
                        Arguments += " -sshauth \"" + ResolvedSSHAuthentication + "\"";
                        Arguments += " -sshuser \"" + ResolvedRSyncUsername + "\"";
                        Arguments += " -rsyncexe \"" + ResolvedRSyncExe + "\"";
                        Arguments += " -overridedevroot \"" + UserDevRootMac + "\"";
                    }

                    // programmers that use Xcode packaging mode should use the following commandline instead, as it will package for Xcode on each compile
                    //				Arguments = "PackageApp " + GameName + " " + Configuration;
                    StubGenerateProcess.StartInfo.Arguments = Arguments;

                    StubGenerateProcess.OutputDataReceived += new DataReceivedEventHandler(OutputReceivedDataEventHandler);
                    StubGenerateProcess.ErrorDataReceived += new DataReceivedEventHandler(OutputReceivedDataEventHandler);

                    OutputReceivedDataEventHandlerEncounteredError = false;
                    OutputReceivedDataEventHandlerEncounteredErrorMessage = "";
                    Utils.RunLocalProcess(StubGenerateProcess);
                    if (OutputReceivedDataEventHandlerEncounteredError)
                    {
                        throw new Exception(OutputReceivedDataEventHandlerEncounteredErrorMessage);
                    }

                    // now that a slow mode sync has finished, we can now do DangerouslyFast mode again (if requested)
                    if (bUseDangerouslyFastModeWasRequested)
                    {
                        File.Create(DangerouslyFastValidFile);
                    }
                    else
                    {
                        // if we didn't want dangerously fast, then delete the file so that setting/unsetting the flag will do the right thing without a Rebuild
                        File.Delete(DangerouslyFastValidFile);
                    }
                }

                {
                    // Copy bundled assets from additional frameworks to the intermediate assets directory (so they can get picked up during staging)
                    String LocalFrameworkAssets = Path.GetFullPath( Target.ProjectDirectory + "/Intermediate/IOS/FrameworkAssets" );
                    String RemoteFrameworkAssets = ConvertPath( LocalFrameworkAssets );

                    CleanIntermediateDirectory( RemoteFrameworkAssets );

                    // Delete the local dest directory if it exists
                    if ( Directory.Exists( LocalFrameworkAssets ) )
                    {
                        Directory.Delete( LocalFrameworkAssets, true );
                    }

                    foreach ( STBuildFramework Framework in RememberedAdditionalFrameworks )
                    {
                        if ( Framework.OwningModule == null || Framework.CopyBundledAssets == null || Framework.CopyBundledAssets == "" )
                        {
                            continue;		// Only care if we need to copy bundle assets
                        }

                        if ( Framework.OwningModule.Target != Target )
                        {
                            continue;		// This framework item doesn't belong to this target, skip it
                        }

                        string RemoteZipPath = GetRemoteIntermediateFrameworkZipPath( Framework );

                        RemoteZipPath = RemoteZipPath.Replace( ".zip", "" );

                        // For now, this is hard coded, but we need to loop over all modules, and copy bundled assets that need it
                        string RemoteSource = RemoteZipPath + "/" + Framework.CopyBundledAssets;
                        string BundleName	= Framework.CopyBundledAssets.Substring( Framework.CopyBundledAssets.LastIndexOf( '/' ) + 1 );

                        String RemoteDest	= RemoteFrameworkAssets + "/" + BundleName;
                        String LocalDest	= LocalFrameworkAssets + "\\" + BundleName;

                        Log.TraceInformation( "Copying bundled asset... RemoteSource: {0}, RemoteDest: {1}, LocalDest: {2}", RemoteSource, RemoteDest, LocalDest );

                        Hashtable Results = RPCUtilHelper.Command( "/", String.Format( "cp -R -L {0} {1}", RemoteSource.Replace(" ", "\\ "), RemoteDest.Replace(" ", "\\ ") ), "", null );

                        foreach ( DictionaryEntry Entry in Results )
                        {
                            Log.TraceInformation( "{0}", Entry.Value );
                        }

                        // Copy the bundled resource from the remote mac to the local dest
                        RPCUtilHelper.CopyDirectory( RemoteDest, LocalDest, RPCUtilHelper.ECopyOptions.None );
                    }
                }
            }
        }
Exemple #13
0
        public override CPPOutput CompileCPPFiles(STBuildTarget Target, CPPEnvironment CompileEnvironment, List<FileItem> SourceFiles, string ModuleName)
        {
            string Arguments = GetCompileArguments_Global(CompileEnvironment);
            string PCHArguments = "";

            if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Include)
            {
                // Add the precompiled header file's path to the include path so GCC can find it.
                // This needs to be before the other include paths to ensure GCC uses it instead of the source header file.
                var PrecompiledFileExtension = STBuildPlatform.BuildPlatformDictionary[STTargetPlatform.IOS].GetBinaryExtension(STBuildBinaryType.PrecompiledHeader);
                PCHArguments += string.Format(" -include \"{0}\"", ConvertPath(CompileEnvironment.PrecompiledHeaderFile.AbsolutePath.Replace(PrecompiledFileExtension, "")));
            }

            // Add include paths to the argument list.
            HashSet<string> AllIncludes = new HashSet<string>(CompileEnvironment.Config.CPPIncludeInfo.IncludePaths);
            AllIncludes.UnionWith(CompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths);
            foreach (string IncludePath in AllIncludes)
            {
                Arguments += string.Format(" -I\"{0}\"", ConvertPath(Path.GetFullPath(IncludePath)));

                if (BuildHostPlatform.Current.Platform != STTargetPlatform.Mac)
                {
                    // sync any third party headers we may need
                    if (IncludePath.Contains("ThirdParty"))
                    {
                        string[] FileList = Directory.GetFiles(IncludePath, "*.h", SearchOption.AllDirectories);
                        foreach (string File in FileList)
                        {
                            FileItem ExternalDependency = FileItem.GetItemByPath(File);
                            LocalToRemoteFileItem(ExternalDependency, true);
                        }

                        FileList = Directory.GetFiles(IncludePath, "*.cpp", SearchOption.AllDirectories);
                        foreach (string File in FileList)
                        {
                            FileItem ExternalDependency = FileItem.GetItemByPath(File);
                            LocalToRemoteFileItem(ExternalDependency, true);
                        }
                    }
                }
            }

            foreach (string Definition in CompileEnvironment.Config.Definitions)
            {
                Arguments += string.Format(" -D\"{0}\"", Definition);
            }

            var BuildPlatform = STBuildPlatform.GetBuildPlatformForCPPTargetPlatform(CompileEnvironment.Config.Target.Platform);

            CPPOutput Result = new CPPOutput();
            // Create a compile action for each source file.
            foreach (FileItem SourceFile in SourceFiles)
            {
                Action CompileAction = new Action(ActionType.Compile);
                string FileArguments = "";
                string Extension = Path.GetExtension(SourceFile.AbsolutePath).ToUpperInvariant();

                if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Create)
                {
                    // Compile the file as a C++ PCH.
                    FileArguments += GetCompileArguments_PCH();
                }
                else if (Extension == ".C")
                {
                    // Compile the file as C code.
                    FileArguments += GetCompileArguments_C();
                }
                else if (Extension == ".CC")
                {
                    // Compile the file as C++ code.
                    FileArguments += GetCompileArguments_CPP();
                }
                else if (Extension == ".MM")
                {
                    // Compile the file as Objective-C++ code.
                    FileArguments += GetCompileArguments_MM();
                }
                else if (Extension == ".M")
                {
                    // Compile the file as Objective-C++ code.
                    FileArguments += GetCompileArguments_M();
                }
                else
                {
                    // Compile the file as C++ code.
                    FileArguments += GetCompileArguments_CPP();

                    // only use PCH for .cpp files
                    FileArguments += PCHArguments;
                }

                // Add the C++ source file and its included files to the prerequisite item list.
                AddPrerequisiteSourceFile( Target, BuildPlatform, CompileEnvironment, SourceFile, CompileAction.PrerequisiteItems );

                if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Create)
                {
                    var PrecompiledFileExtension = STBuildPlatform.BuildPlatformDictionary[STTargetPlatform.IOS].GetBinaryExtension(STBuildBinaryType.PrecompiledHeader);
                    // Add the precompiled header file to the produced item list.
                    FileItem PrecompiledHeaderFile = FileItem.GetItemByPath(
                        Path.Combine(
                            CompileEnvironment.Config.OutputDirectory,
                        Path.GetFileName(SourceFile.AbsolutePath) + PrecompiledFileExtension
                            )
                        );

                    FileItem RemotePrecompiledHeaderFile = LocalToRemoteFileItem(PrecompiledHeaderFile, false);
                    CompileAction.ProducedItems.Add(RemotePrecompiledHeaderFile);
                    Result.PrecompiledHeaderFile = RemotePrecompiledHeaderFile;

                    // Add the parameters needed to compile the precompiled header file to the command-line.
                    FileArguments += string.Format(" -o \"{0}\"", RemotePrecompiledHeaderFile.AbsolutePath, false);
                }
                else
                {
                    if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Include)
                    {
                        CompileAction.bIsUsingPCH = true;
                        CompileAction.PrerequisiteItems.Add(CompileEnvironment.PrecompiledHeaderFile);
                    }
                    var ObjectFileExtension = STBuildPlatform.BuildPlatformDictionary[STTargetPlatform.IOS].GetBinaryExtension(STBuildBinaryType.Object);
                    // Add the object file to the produced item list.
                    FileItem ObjectFile = FileItem.GetItemByPath(
                        Path.Combine(
                            CompileEnvironment.Config.OutputDirectory,
                            Path.GetFileName(SourceFile.AbsolutePath) + ObjectFileExtension
                            )
                        );

                    FileItem RemoteObjectFile = LocalToRemoteFileItem(ObjectFile, false);
                    CompileAction.ProducedItems.Add(RemoteObjectFile);
                    Result.ObjectFiles.Add(RemoteObjectFile);
                    FileArguments += string.Format(" -o \"{0}\"", RemoteObjectFile.AbsolutePath, false);
                }

                // Add the source file path to the command-line.
                FileArguments += string.Format(" \"{0}\"", ConvertPath(SourceFile.AbsolutePath), false);

                string CompilerPath = XcodeDeveloperDir + "Toolchains/XcodeDefault.xctoolchain/usr/bin/" + IOSCompiler;
                if (!Utils.IsRunningOnMono && BuildHostPlatform.Current.Platform != STTargetPlatform.Mac)
                {
                    CompileAction.ActionHandler = new Action.BlockingActionHandler(RPCUtilHelper.RPCActionHandler);
                }

                // RPC utility parameters are in terms of the Mac side
                CompileAction.WorkingDirectory = GetMacDevSrcRoot();
                CompileAction.CommandPath = CompilerPath;
                CompileAction.CommandArguments = Arguments + FileArguments + CompileEnvironment.Config.AdditionalArguments;
                CompileAction.StatusDescription = string.Format("{0}", Path.GetFileName(SourceFile.AbsolutePath));
                CompileAction.bIsGCCCompiler = true;
                // We're already distributing the command by execution on Mac.
                CompileAction.bCanExecuteRemotely = false;
                CompileAction.bShouldOutputStatusDescription = true;
                CompileAction.OutputEventHandler = new DataReceivedEventHandler(RemoteOutputReceivedEventHandler);
            }
            return Result;
        }
Exemple #14
0
        /// <summary>
        /// Saves the action graph (and include dependency network) to a graph gile
        /// </summary>
        /// <param name="Filename">File name to emit</param>
        /// <param name="Description">Description to be stored in graph metadata</param>
        /// <param name="VisualizationType">Type of graph to create</param>
        /// <param name="Actions">All actions</param>
        /// <param name="IncludeCompileActions">True if we should include compile actions.  If disabled, only the static link actions will be shown, which is useful to see module relationships</param>
        public static void SaveActionGraphVisualization(STBuildTarget Target, string Filename, string Description, ActionGraphVisualizationType VisualizationType, List<Action> Actions, bool IncludeCompileActions = true)
        {
            // True if we should include individual files in the graph network, or false to include only the build actions
            var IncludeFiles = VisualizationType != ActionGraphVisualizationType.OnlyActions;
            var OnlyIncludeCPlusPlusFiles = VisualizationType == ActionGraphVisualizationType.OnlyCPlusPlusFilesAndHeaders;

            // True if want to show actions in the graph, otherwise we're only showing files
            var IncludeActions = VisualizationType != ActionGraphVisualizationType.OnlyFilesAndHeaders && VisualizationType != ActionGraphVisualizationType.OnlyCPlusPlusFilesAndHeaders;

            // True if C++ header dependencies should be expanded into the graph, or false to only have .cpp files
            var ExpandCPPHeaderDependencies = IncludeFiles && (VisualizationType == ActionGraphVisualizationType.ActionsWithFilesAndHeaders || VisualizationType == ActionGraphVisualizationType.OnlyFilesAndHeaders || VisualizationType == ActionGraphVisualizationType.OnlyCPlusPlusFilesAndHeaders);

            var TimerStartTime = DateTime.UtcNow;

            var GraphNodes = new List<GraphNode>();

            var FileToGraphNodeMap = new Dictionary<FileItem, GraphNode>();

            // Filter our list of actions
            var FilteredActions = new List<Action>();
            {
                for (var ActionIndex = 0; ActionIndex < Actions.Count; ++ActionIndex)
                {
                    var Action = Actions[ActionIndex];

                    if (!IncludeActions || IncludeCompileActions || (Action.ActionType != ActionType.Compile))
                    {
                        FilteredActions.Add(Action);
                    }
                }
            }

            var FilesToCreateNodesFor = new HashSet<FileItem>();
            for (var ActionIndex = 0; ActionIndex < FilteredActions.Count; ++ActionIndex)
            {
                var Action = FilteredActions[ActionIndex];

                if (IncludeActions)
                {
                    var GraphNode = new GraphNode()
                    {
                        Id = GraphNodes.Count,

                        // Don't bother including "Link" text if we're excluding compile actions
                        Label = IncludeCompileActions ? (Action.ActionType.ToString() + " " + Action.StatusDescription) : Action.StatusDescription
                    };

                    switch (Action.ActionType)
                    {
                        case ActionType.BuildProject:
                            GraphNode.Color = new GraphColor() { R = 0.3f, G = 1.0f, B = 1.0f, A = 1.0f };
                            GraphNode.Size = 1.1f;
                            break;

                        case ActionType.Compile:
                            GraphNode.Color = new GraphColor() { R = 0.3f, G = 1.0f, B = 0.3f, A = 1.0f };
                            break;

                        case ActionType.Link:
                            GraphNode.Color = new GraphColor() { R = 0.3f, G = 0.3f, B = 1.0f, A = 1.0f };
                            GraphNode.Size = 1.2f;
                            break;
                    }

                    GraphNodes.Add(GraphNode);
                }

                if (IncludeFiles)
                {
                    foreach (var ProducedFileItem in Action.ProducedItems)
                    {
                        if (!OnlyIncludeCPlusPlusFiles || IsCPPFile(ProducedFileItem))
                        {
                            FilesToCreateNodesFor.Add(ProducedFileItem);
                        }
                    }

                    foreach (var PrerequisiteFileItem in Action.PrerequisiteItems)
                    {
                        if (!OnlyIncludeCPlusPlusFiles || IsCPPFile(PrerequisiteFileItem))
                        {
                            FilesToCreateNodesFor.Add(PrerequisiteFileItem);
                        }
                    }
                }
            }

            var OverriddenPrerequisites = new Dictionary<FileItem, List<FileItem>>();

            // Determine the average size of all of the C++ source files
            Int64 AverageCPPFileSize;
            {
                Int64 TotalFileSize = 0;
                int CPPFileCount = 0;
                foreach (var FileItem in FilesToCreateNodesFor)
                {
                    if (IsCPPFile(FileItem))
                    {
                        ++CPPFileCount;
                        TotalFileSize += new FileInfo(FileItem.AbsolutePath).Length;
                    }
                }

                if (CPPFileCount > 0)
                {
                    AverageCPPFileSize = TotalFileSize / CPPFileCount;
                }
                else
                {
                    AverageCPPFileSize = 1;
                }
            }

            var BuildPlatform = STBuildPlatform.GetBuildPlatform(STTargetPlatform.Win64);

            foreach (var FileItem in FilesToCreateNodesFor)
            {
                var FileGraphNode = new GraphNode()
                {
                    Id = GraphNodes.Count,
                    Label = Path.GetFileName(FileItem.AbsolutePath)
                };

                if (FileItem.AbsolutePath.EndsWith(".h", StringComparison.InvariantCultureIgnoreCase) ||
                    FileItem.AbsolutePath.EndsWith(".inl", StringComparison.InvariantCultureIgnoreCase))
                {
                    // Header file
                    FileGraphNode.Color = new GraphColor() { R = 0.9f, G = 0.2f, B = 0.9f, A = 1.0f };
                }
                else if (FileItem.AbsolutePath.EndsWith(".cpp", StringComparison.InvariantCultureIgnoreCase) ||
                         FileItem.AbsolutePath.EndsWith(".c", StringComparison.InvariantCultureIgnoreCase) ||
                         FileItem.AbsolutePath.EndsWith(".mm", StringComparison.InvariantCultureIgnoreCase))
                {
                    // C++ file
                    FileGraphNode.Color = new GraphColor() { R = 1.0f, G = 1.0f, B = 0.3f, A = 1.0f };
                }
                else
                {
                    // Other file
                    FileGraphNode.Color = new GraphColor() { R = 0.4f, G = 0.4f, B = 0.1f, A = 1.0f };
                }

                // Set the size of the file node based on the size of the file on disk
                var bIsCPPFile = IsCPPFile(FileItem);
                if (bIsCPPFile)
                {
                    var MinNodeSize = 0.25f;
                    var MaxNodeSize = 2.0f;
                    var FileSize = new FileInfo(FileItem.AbsolutePath).Length;
                    float FileSizeScale = (float)((double)FileSize / (double)AverageCPPFileSize);

                    var SourceFileSizeScaleFactor = 0.1f;		// How much to make nodes for files bigger or larger based on their difference from the average file's size
                    FileGraphNode.Size = Math.Min(Math.Max(1.0f + SourceFileSizeScaleFactor * FileSizeScale, MinNodeSize), MaxNodeSize);
                }

                //@todo: Testing out attribute support.  Replace with an attribute that is actually useful!
                //if( FileItem.PrecompiledHeaderIncludeFilename != null )
                //{
                //FileGraphNode.Attributes[ "PCHFile" ] = Path.GetFileNameWithoutExtension( FileItem.PrecompiledHeaderIncludeFilename );
                //}

                FileToGraphNodeMap[FileItem] = FileGraphNode;
                GraphNodes.Add(FileGraphNode);

                if (ExpandCPPHeaderDependencies && bIsCPPFile)
                {
                    bool HasUObjects;
                    List<DependencyInclude> DirectlyIncludedFilenames = CPPEnvironment.GetDirectIncludeDependencies(Target, FileItem, BuildPlatform, bOnlyCachedDependencies: false, HasUObjects: out HasUObjects);

                    // Resolve the included file name to an actual file.
                    var DirectlyIncludedFiles =
                        DirectlyIncludedFilenames
                        .Where(DirectlyIncludedFilename => !string.IsNullOrEmpty(DirectlyIncludedFilename.IncludeResolvedName))
                        .Select(DirectlyIncludedFilename => DirectlyIncludedFilename.IncludeResolvedName)
                        // Skip same include over and over (.inl files)
                        .Distinct()
                        .Select(FileItem.GetItemByFullPath)
                        .ToList();

                    OverriddenPrerequisites[FileItem] = DirectlyIncludedFiles;
                }
            }

            // Connect everything together
            var GraphEdges = new List<GraphEdge>();

            if (IncludeActions)
            {
                for (var ActionIndex = 0; ActionIndex < FilteredActions.Count; ++ActionIndex)
                {
                    var Action = FilteredActions[ActionIndex];
                    var ActionGraphNode = GraphNodes[ActionIndex];

                    List<FileItem> ActualPrerequisiteItems = Action.PrerequisiteItems;
                    if (IncludeFiles && ExpandCPPHeaderDependencies && Action.ActionType == ActionType.Compile)
                    {
                        // The first prerequisite is always the .cpp file to compile
                        var CPPFile = Action.PrerequisiteItems[0];
                        if (!IsCPPFile(CPPFile))
                        {
                            throw new BuildException("Was expecting a C++ file as the first prerequisite for a Compile action");
                        }

                        ActualPrerequisiteItems = new List<FileItem>();
                        ActualPrerequisiteItems.Add(CPPFile);
                    }

                    foreach (var PrerequisiteFileItem in ActualPrerequisiteItems)
                    {
                        if (IncludeFiles)
                        {
                            GraphNode PrerequisiteFileGraphNode;
                            if (FileToGraphNodeMap.TryGetValue(PrerequisiteFileItem, out PrerequisiteFileGraphNode))
                            {
                                // Connect a file our action is dependent on, to our action itself
                                var GraphEdge = new GraphEdge()
                                {
                                    Id = GraphEdges.Count,
                                    Source = PrerequisiteFileGraphNode,
                                    Target = ActionGraphNode,
                                };

                                GraphEdges.Add(GraphEdge);
                            }
                            else
                            {
                                // Not a file we were tracking
                                // Console.WriteLine( "Unknown file: " + PrerequisiteFileItem.AbsolutePath );
                            }
                        }
                        else if (PrerequisiteFileItem.ProducingAction != null)
                        {
                            // Not showing files, so connect the actions together
                            var ProducingActionIndex = FilteredActions.IndexOf(PrerequisiteFileItem.ProducingAction);
                            if (ProducingActionIndex != -1)
                            {
                                var SourceGraphNode = GraphNodes[ProducingActionIndex];

                                var GraphEdge = new GraphEdge()
                                {
                                    Id = GraphEdges.Count,
                                    Source = SourceGraphNode,
                                    Target = ActionGraphNode,
                                };

                                GraphEdges.Add(GraphEdge);
                            }
                            else
                            {
                                // Our producer action was filtered out
                            }
                        }
                    }

                    foreach (var ProducedFileItem in Action.ProducedItems)
                    {
                        if (IncludeFiles)
                        {
                            if (!OnlyIncludeCPlusPlusFiles || IsCPPFile(ProducedFileItem))
                            {
                                var ProducedFileGraphNode = FileToGraphNodeMap[ProducedFileItem];

                                var GraphEdge = new GraphEdge()
                                {
                                    Id = GraphEdges.Count,
                                    Source = ActionGraphNode,
                                    Target = ProducedFileGraphNode,
                                };

                                GraphEdges.Add(GraphEdge);
                            }
                        }
                    }
                }
            }

            if (IncludeFiles && ExpandCPPHeaderDependencies)
            {
                // Fill in overridden prerequisites
                foreach (var FileAndPrerequisites in OverriddenPrerequisites)
                {
                    var FileItem = FileAndPrerequisites.Key;
                    var FilePrerequisites = FileAndPrerequisites.Value;

                    var FileGraphNode = FileToGraphNodeMap[FileItem];
                    foreach (var PrerequisiteFileItem in FilePrerequisites)
                    {
                        GraphNode PrerequisiteFileGraphNode;
                        if (FileToGraphNodeMap.TryGetValue(PrerequisiteFileItem, out PrerequisiteFileGraphNode))
                        {
                            var GraphEdge = new GraphEdge()
                            {
                                Id = GraphEdges.Count,
                                Source = PrerequisiteFileGraphNode,
                                Target = FileGraphNode,
                            };

                            GraphEdges.Add(GraphEdge);
                        }
                        else
                        {
                            // Some other header that we don't track directly
                            //Console.WriteLine( "File not known: " + PrerequisiteFileItem.AbsolutePath );
                        }
                    }
                }
            }

            GraphVisualization.WriteGraphFile(Filename, Description, GraphNodes, GraphEdges);

            if (BuildConfiguration.bPrintPerformanceInfo)
            {
                var TimerDuration = DateTime.UtcNow - TimerStartTime;
                Log.TraceInformation("Generating and saving ActionGraph took " + TimerDuration.TotalSeconds + "s");
            }
        }
Exemple #15
0
        /**
         * Determines whether an action is outdated based on the modification times for its prerequisite
         * and produced items.
         * @param RootAction - The action being considered.
         * @param OutdatedActionDictionary -
         * @return true if outdated
         */
        public static bool IsActionOutdated(STBuildTarget Target, Action RootAction, ref Dictionary<Action, bool> OutdatedActionDictionary, ActionHistory ActionHistory, Dictionary<STBuildTarget, List<FileItem>> TargetToOutdatedPrerequisitesMap)
        {
            // Only compute the outdated-ness for actions that don't aren't cached in the outdated action dictionary.
            bool bIsOutdated = false;
            if (!OutdatedActionDictionary.TryGetValue(RootAction, out bIsOutdated))
            {
                // Determine the last time the action was run based on the write times of its produced files.
                string LatestUpdatedProducedItemName = null;
                DateTimeOffset LastExecutionTime = DateTimeOffset.MaxValue;
                foreach (FileItem ProducedItem in RootAction.ProducedItems)
                {
                    // Optionally skip the action history check, as this only works for local builds
                    if (BuildConfiguration.bUseActionHistory)
                    {
                        // Check if the command-line of the action previously used to produce the item is outdated.
                        string OldProducingCommandLine = "";
                        string NewProducingCommandLine = RootAction.CommandPath + " " + RootAction.CommandArguments;
                        if (!ActionHistory.GetProducingCommandLine(ProducedItem, out OldProducingCommandLine)
                        || !String.Equals(OldProducingCommandLine, NewProducingCommandLine, StringComparison.InvariantCultureIgnoreCase))
                        {
                            Log.TraceVerbose(
                                "{0}: Produced item \"{1}\" was produced by outdated command-line.\nOld command-line: {2}\nNew command-line: {3}",
                                RootAction.StatusDescription,
                                Path.GetFileName(ProducedItem.AbsolutePath),
                                OldProducingCommandLine,
                                NewProducingCommandLine
                                );

                            bIsOutdated = true;

                            // Update the command-line used to produce this item in the action history.
                            ActionHistory.SetProducingCommandLine(ProducedItem, NewProducingCommandLine);
                        }
                    }

                    // If the produced file doesn't exist or has zero size, consider it outdated.  The zero size check is to detect cases
                    // where aborting an earlier compile produced invalid zero-sized obj files, but that may cause actions where that's
                    // legitimate output to always be considered outdated.
                    if (ProducedItem.bExists && (ProducedItem.bIsRemoteFile || ProducedItem.Length > 0 || ProducedItem.IsDirectory))
                    {
                        // When linking incrementally, don't use LIB, EXP pr PDB files when checking for the oldest produced item,
                        // as those files aren't always touched.
                        if (BuildConfiguration.bUseIncrementalLinking)
                        {
                            String ProducedItemExtension = Path.GetExtension(ProducedItem.AbsolutePath).ToUpperInvariant();
                            if (ProducedItemExtension == ".LIB" || ProducedItemExtension == ".EXP" || ProducedItemExtension == ".PDB")
                            {
                                continue;
                            }
                        }

                        // Use the oldest produced item's time as the last execution time.
                        if (ProducedItem.LastWriteTime < LastExecutionTime)
                        {
                            LastExecutionTime = ProducedItem.LastWriteTime;
                            LatestUpdatedProducedItemName = ProducedItem.AbsolutePath;
                        }
                    }
                    else
                    {
                        // If any of the produced items doesn't exist, the action is outdated.
                        Log.TraceVerbose(
                            "{0}: Produced item \"{1}\" doesn't exist.",
                            RootAction.StatusDescription,
                            Path.GetFileName(ProducedItem.AbsolutePath)
                            );
                        bIsOutdated = true;
                    }
                }

                Log.WriteLineIf(BuildConfiguration.bLogDetailedActionStats && !String.IsNullOrEmpty(LatestUpdatedProducedItemName),
                    TraceEventType.Verbose, "{0}: Oldest produced item is {1}", RootAction.StatusDescription, LatestUpdatedProducedItemName);

                bool bFindCPPIncludePrerequisites = false;
                if (RootAction.ActionType == ActionType.Compile)
                {
                    // Outdated targets don't need their headers scanned yet, because presumably they would already be out of dated based on already-cached
                    // includes before getting this far.  However, if we find them to be outdated after processing includes, we'll do a deep scan later
                    // on and cache all of the includes so that we have them for a quick outdatedness check the next run.
                    if (!bIsOutdated &&
                        BuildConfiguration.bUseExperimentalFastBuildIteration &&
                        STBuildTool.IsAssemblingBuild &&
                        RootAction.ActionType == ActionType.Compile)
                    {
                        bFindCPPIncludePrerequisites = true;
                    }

                    // Were we asked to force an update of our cached includes BEFORE we try to build?  This may be needed if our cache can no longer
                    // be trusted and we need to fill it with perfectly valid data (even if we're in assembler only mode)
                    if (BuildConfiguration.bUseExperimentalFastDependencyScan &&
                        STBuildTool.bNeedsFullCPPIncludeRescan)
                    {
                        bFindCPPIncludePrerequisites = true;
                    }
                }

                if (bFindCPPIncludePrerequisites)
                {
                    // Scan this file for included headers that may be out of date.  Note that it's OK if we break out early because we found
                    // the action to be outdated.  For outdated actions, we kick off a separate include scan in a background thread later on to
                    // catch all of the other includes and form an exhaustive set.
                    foreach (FileItem PrerequisiteItem in RootAction.PrerequisiteItems)
                    {
                        // @todo ubtmake: Make sure we are catching RC files here too.  Anything that the toolchain would have tried it on.  Logic should match the CACHING stuff below
                        if (PrerequisiteItem.CachedCPPIncludeInfo != null)
                        {
                            var BuildPlatform = STBuildPlatform.GetBuildPlatform(Target.GetTargetInfo().Platform);
                            var IncludedFileList = CPPEnvironment.FindAndCacheAllIncludedFiles(Target, PrerequisiteItem, BuildPlatform, PrerequisiteItem.CachedCPPIncludeInfo, bOnlyCachedDependencies: BuildConfiguration.bUseExperimentalFastDependencyScan);
                            foreach (var IncludedFile in IncludedFileList)	// @todo fastubt: @todo ubtmake: Optimization: This is "retesting" a lot of the same files over and over in a single run (common indirect includes)
                            {
                                if (IncludedFile.bExists)
                                {
                                    // allow a 1 second slop for network copies
                                    TimeSpan TimeDifference = IncludedFile.LastWriteTime - LastExecutionTime;
                                    bool bPrerequisiteItemIsNewerThanLastExecution = TimeDifference.TotalSeconds > 1;
                                    if (bPrerequisiteItemIsNewerThanLastExecution)
                                    {
                                        Log.TraceVerbose(
                                            "{0}: Included file {1} is newer than the last execution of the action: {2} vs {3}",
                                            RootAction.StatusDescription,
                                            Path.GetFileName(IncludedFile.AbsolutePath),
                                            IncludedFile.LastWriteTime.LocalDateTime,
                                            LastExecutionTime.LocalDateTime
                                            );
                                        bIsOutdated = true;

                                        // Don't bother checking every single include if we've found one that is out of date
                                        break;
                                    }
                                }
                            }
                        }

                        if (bIsOutdated)
                        {
                            break;
                        }
                    }
                }

                if (!bIsOutdated)
                {
                    // Check if any of the prerequisite items are produced by outdated actions, or have changed more recently than
                    // the oldest produced item.
                    foreach (FileItem PrerequisiteItem in RootAction.PrerequisiteItems)
                    {
                        // Only check for outdated import libraries if we were configured to do so.  Often, a changed import library
                        // won't affect a dependency unless a public header file was also changed, in which case we would be forced
                        // to recompile anyway.  This just allows for faster iteration when working on a subsystem in a DLL, as we
                        // won't have to wait for dependent targets to be relinked after each change.
                        bool bIsImportLibraryFile = false;
                        if (PrerequisiteItem.ProducingAction != null && PrerequisiteItem.ProducingAction.bProducesImportLibrary)
                        {
                            bIsImportLibraryFile = PrerequisiteItem.AbsolutePath.EndsWith(".LIB", StringComparison.InvariantCultureIgnoreCase);
                        }
                        if (!bIsImportLibraryFile || !BuildConfiguration.bIgnoreOutdatedImportLibraries)
                        {
                            // If the prerequisite is produced by an outdated action, then this action is outdated too.
                            if (PrerequisiteItem.ProducingAction != null)
                            {
                                if (IsActionOutdated(Target, PrerequisiteItem.ProducingAction, ref OutdatedActionDictionary, ActionHistory, TargetToOutdatedPrerequisitesMap))
                                {
                                    Log.TraceVerbose(
                                        "{0}: Prerequisite {1} is produced by outdated action.",
                                        RootAction.StatusDescription,
                                        Path.GetFileName(PrerequisiteItem.AbsolutePath)
                                        );
                                    bIsOutdated = true;
                                }
                            }

                            if (PrerequisiteItem.bExists)
                            {
                                // allow a 1 second slop for network copies
                                TimeSpan TimeDifference = PrerequisiteItem.LastWriteTime - LastExecutionTime;
                                bool bPrerequisiteItemIsNewerThanLastExecution = TimeDifference.TotalSeconds > 1;
                                if (bPrerequisiteItemIsNewerThanLastExecution)
                                {
                                    Log.TraceVerbose(
                                        "{0}: Prerequisite {1} is newer than the last execution of the action: {2} vs {3}",
                                        RootAction.StatusDescription,
                                        Path.GetFileName(PrerequisiteItem.AbsolutePath),
                                        PrerequisiteItem.LastWriteTime.LocalDateTime,
                                        LastExecutionTime.LocalDateTime
                                        );
                                    bIsOutdated = true;
                                }
                            }

                            // GatherAllOutdatedActions will ensure all actions are checked for outdated-ness, so we don't need to recurse with
                            // all this action's prerequisites once we've determined it's outdated.
                            if (bIsOutdated)
                            {
                                break;
                            }
                        }
                    }
                }

                // For compile actions, we have C++ files that are actually dependent on header files that could have been changed.  We only need to
                // know about the set of header files that are included for files that are already determined to be out of date (such as if the file
                // is missing or was modified.)  In the case that the file is out of date, we'll perform a deep scan to update our cached set of
                // includes for this file, so that we'll be able to determine whether it is out of date next time very quickly.
                if (BuildConfiguration.bUseExperimentalFastDependencyScan)
                {
                    var DeepIncludeScanStartTime = DateTime.UtcNow;

                    // @todo fastubt: we may be scanning more files than we need to here -- indirectly outdated files are bIsOutdated=true by this point (for example basemost includes when deeper includes are dirty)
                    if (bIsOutdated && RootAction.ActionType == ActionType.Compile)	// @todo fastubt: Does this work with RC files?  See above too.
                    {
                        Log.TraceVerbose("Outdated action: {0}", RootAction.StatusDescription);
                        foreach (FileItem PrerequisiteItem in RootAction.PrerequisiteItems)
                        {
                            if (PrerequisiteItem.CachedCPPIncludeInfo != null)
                            {
                                if (!IsCPPFile(PrerequisiteItem))
                                {
                                    throw new BuildException("Was only expecting C++ files to have CachedCPPEnvironments!");
                                }
                                Log.TraceVerbose("  -> DEEP include scan: {0}", PrerequisiteItem.AbsolutePath);

                                List<FileItem> OutdatedPrerequisites;
                                if (!TargetToOutdatedPrerequisitesMap.TryGetValue(Target, out OutdatedPrerequisites))
                                {
                                    OutdatedPrerequisites = new List<FileItem>();
                                    TargetToOutdatedPrerequisitesMap.Add(Target, OutdatedPrerequisites);
                                }

                                OutdatedPrerequisites.Add(PrerequisiteItem);
                            }
                            else if (IsCPPImplementationFile(PrerequisiteItem) || IsCPPResourceFile(PrerequisiteItem))
                            {
                                if (PrerequisiteItem.CachedCPPIncludeInfo == null)
                                {
                                    Log.TraceVerbose("  -> WARNING: No CachedCPPEnvironment: {0}", PrerequisiteItem.AbsolutePath);
                                }
                            }
                        }
                    }

                    if (BuildConfiguration.bPrintPerformanceInfo)
                    {
                        double DeepIncludeScanTime = (DateTime.UtcNow - DeepIncludeScanStartTime).TotalSeconds;
                        STBuildTool.TotalDeepIncludeScanTime += DeepIncludeScanTime;
                    }
                }

                // Cache the outdated-ness of this action.
                OutdatedActionDictionary.Add(RootAction, bIsOutdated);
            }

            return bIsOutdated;
        }
Exemple #16
0
 public STBuildModuleCPPCLR(
     STBuildTarget InTarget,
     string InName,
     STBuildModuleType InType,
     string InModuleDirectory,
     string InOutputDirectory,
     bool? InIsRedistributableOverride,
     IntelliSenseGatherer InIntelliSenseGatherer,
     IEnumerable<FileItem> InSourceFiles,
     IEnumerable<string> InPublicIncludePaths,
     IEnumerable<string> InPublicSystemIncludePaths,
     IEnumerable<string> InDefinitions,
     IEnumerable<string> InPrivateAssemblyReferences,
     IEnumerable<string> InPublicIncludePathModuleNames,
     IEnumerable<string> InPublicDependencyModuleNames,
     IEnumerable<string> InPublicDelayLoadDLLs,
     IEnumerable<string> InPublicAdditionalLibraries,
     IEnumerable<string> InPublicFrameworks,
     IEnumerable<string> InPublicWeakFrameworks,
     IEnumerable<STBuildFramework> InPublicAdditionalFrameworks,
     IEnumerable<string> InPublicAdditionalShadowFiles,
     IEnumerable<STBuildBundleResource> InPublicAdditionalBundleResources,
     IEnumerable<string> InPrivateIncludePaths,
     IEnumerable<string> InPrivateIncludePathModuleNames,
     IEnumerable<string> InPrivateDependencyModuleNames,
     IEnumerable<string> InCircularlyReferencedDependentModules,
     IEnumerable<string> InDynamicallyLoadedModuleNames,
     IEnumerable<string> InPlatformSpecificDynamicallyLoadedModuleNames,
     ModuleRules.CodeOptimization InOptimizeCode,
     bool InAllowSharedPCH,
     string InSharedPCHHeaderFile,
     bool InUseRTTI,
     bool InEnableBufferSecurityChecks,
     bool InFasterWithoutUnity,
     int InMinFilesUsingPrecompiledHeaderOverride,
     bool InEnableExceptions,
     bool bInBuildSourceFiles
     )
     : base(InTarget, InName, InType, InModuleDirectory, InOutputDirectory, InIsRedistributableOverride, InIntelliSenseGatherer,
     InSourceFiles, InPublicIncludePaths, InPublicSystemIncludePaths, InDefinitions,
     InPublicIncludePathModuleNames, InPublicDependencyModuleNames, InPublicDelayLoadDLLs, InPublicAdditionalLibraries, InPublicFrameworks, InPublicWeakFrameworks, InPublicAdditionalFrameworks, InPublicAdditionalShadowFiles, InPublicAdditionalBundleResources,
     InPrivateIncludePaths, InPrivateIncludePathModuleNames, InPrivateDependencyModuleNames,
     InCircularlyReferencedDependentModules, InDynamicallyLoadedModuleNames, InPlatformSpecificDynamicallyLoadedModuleNames, InOptimizeCode,
     InAllowSharedPCH, InSharedPCHHeaderFile, InUseRTTI, InEnableBufferSecurityChecks, InFasterWithoutUnity, InMinFilesUsingPrecompiledHeaderOverride,
     InEnableExceptions, bInBuildSourceFiles)
 {
     PrivateAssemblyReferences = HashSetFromOptionalEnumerableStringParameter(InPrivateAssemblyReferences);
 }
Exemple #17
0
        public STBuildModule(
            STBuildTarget InTarget,
            string InName,
            STBuildModuleType InType,
            string InModuleDirectory,
            string InOutputDirectory,
            bool? InIsRedistributableOverride,
            IEnumerable<string> InPublicDefinitions = null,
            IEnumerable<string> InPublicIncludePaths = null,
            IEnumerable<string> InPublicSystemIncludePaths = null,
            IEnumerable<string> InPublicLibraryPaths = null,
            IEnumerable<string> InPublicAdditionalLibraries = null,
            IEnumerable<string> InPublicFrameworks = null,
            IEnumerable<string> InPublicWeakFrameworks = null,
            IEnumerable<STBuildFramework> InPublicAdditionalFrameworks = null,
            IEnumerable<string> InPublicAdditionalShadowFiles = null,
            IEnumerable<STBuildBundleResource> InPublicAdditionalBundleResources = null,
            IEnumerable<string> InPublicIncludePathModuleNames = null,
            IEnumerable<string> InPublicDependencyModuleNames = null,
            IEnumerable<string> InPublicDelayLoadDLLs = null,
            IEnumerable<string> InPrivateIncludePaths = null,
            IEnumerable<string> InPrivateIncludePathModuleNames = null,
            IEnumerable<string> InPrivateDependencyModuleNames = null,
            IEnumerable<string> InCircularlyReferencedDependentModules = null,
            IEnumerable<string> InDynamicallyLoadedModuleNames = null,
            IEnumerable<string> InPlatformSpecificDynamicallyLoadedModuleNames = null
            )
        {
            Target = InTarget;
            Name = InName;
            Type = InType;
            ModuleDirectory = InModuleDirectory;
            OutputDirectory = InOutputDirectory;
            PublicDefinitions = HashSetFromOptionalEnumerableStringParameter(InPublicDefinitions);
            PublicIncludePaths = HashSetFromOptionalEnumerableStringParameter(InPublicIncludePaths);
            PublicSystemIncludePaths = HashSetFromOptionalEnumerableStringParameter(InPublicSystemIncludePaths);
            PublicLibraryPaths = HashSetFromOptionalEnumerableStringParameter(InPublicLibraryPaths);
            PublicAdditionalLibraries = HashSetFromOptionalEnumerableStringParameter(InPublicAdditionalLibraries);
            PublicFrameworks = HashSetFromOptionalEnumerableStringParameter(InPublicFrameworks);
            PublicWeakFrameworks = HashSetFromOptionalEnumerableStringParameter(InPublicWeakFrameworks);
            PublicAdditionalFrameworks = InPublicAdditionalFrameworks == null ? new HashSet<STBuildFramework>() : new HashSet<STBuildFramework>(InPublicAdditionalFrameworks);
            PublicAdditionalShadowFiles = HashSetFromOptionalEnumerableStringParameter(InPublicAdditionalShadowFiles);
            PublicAdditionalBundleResources = InPublicAdditionalBundleResources == null ? new HashSet<STBuildBundleResource>() : new HashSet<STBuildBundleResource>(InPublicAdditionalBundleResources);
            PublicIncludePathModuleNames = HashSetFromOptionalEnumerableStringParameter(InPublicIncludePathModuleNames);
            PublicDependencyModuleNames = HashSetFromOptionalEnumerableStringParameter(InPublicDependencyModuleNames);
            PublicDelayLoadDLLs = HashSetFromOptionalEnumerableStringParameter(InPublicDelayLoadDLLs);
            PrivateIncludePaths = HashSetFromOptionalEnumerableStringParameter(InPrivateIncludePaths);
            PrivateIncludePathModuleNames = HashSetFromOptionalEnumerableStringParameter(InPrivateIncludePathModuleNames);
            PrivateDependencyModuleNames = HashSetFromOptionalEnumerableStringParameter(InPrivateDependencyModuleNames);
            CircularlyReferencedDependentModules = new HashSet<string>(HashSetFromOptionalEnumerableStringParameter(InCircularlyReferencedDependentModules));
            DynamicallyLoadedModuleNames = HashSetFromOptionalEnumerableStringParameter(InDynamicallyLoadedModuleNames);
            PlatformSpecificDynamicallyLoadedModuleNames = HashSetFromOptionalEnumerableStringParameter(InPlatformSpecificDynamicallyLoadedModuleNames);
            IsRedistributableOverride = InIsRedistributableOverride;

            Target.RegisterModule(this);
        }
Exemple #18
0
        public STBuildModuleCPP(
            STBuildTarget InTarget,
            string InName,
            STBuildModuleType InType,
            string InModuleDirectory,
            string InOutputDirectory,
            bool? InIsRedistributableOverride,
            IntelliSenseGatherer InIntelliSenseGatherer,
            IEnumerable<FileItem> InSourceFiles,
            IEnumerable<string> InPublicIncludePaths,
            IEnumerable<string> InPublicSystemIncludePaths,
            IEnumerable<string> InDefinitions,
            IEnumerable<string> InPublicIncludePathModuleNames,
            IEnumerable<string> InPublicDependencyModuleNames,
            IEnumerable<string> InPublicDelayLoadDLLs,
            IEnumerable<string> InPublicAdditionalLibraries,
            IEnumerable<string> InPublicFrameworks,
            IEnumerable<string> InPublicWeakFrameworks,
            IEnumerable<STBuildFramework> InPublicAdditionalFrameworks,
            IEnumerable<string> InPublicAdditionalShadowFiles,
            IEnumerable<STBuildBundleResource> InPublicAdditionalBundleResources,
            IEnumerable<string> InPrivateIncludePaths,
            IEnumerable<string> InPrivateIncludePathModuleNames,
            IEnumerable<string> InPrivateDependencyModuleNames,
            IEnumerable<string> InCircularlyReferencedDependentModules,
            IEnumerable<string> InDynamicallyLoadedModuleNames,
            IEnumerable<string> InPlatformSpecificDynamicallyLoadedModuleNames,
            ModuleRules.CodeOptimization InOptimizeCode,
            bool InAllowSharedPCH,
            string InSharedPCHHeaderFile,
            bool InUseRTTI,
            bool InEnableBufferSecurityChecks,
            bool InFasterWithoutUnity,
            int InMinFilesUsingPrecompiledHeaderOverride,
            bool InEnableExceptions,
            bool bInBuildSourceFiles
            )
            : base(InTarget,
                    InName,
                    InType,
                    InModuleDirectory,
                    InOutputDirectory,
                    InIsRedistributableOverride,
                    InDefinitions,
                    InPublicIncludePaths,
                    InPublicSystemIncludePaths,
                    null,
                    InPublicAdditionalLibraries,
                    InPublicFrameworks,
                    InPublicWeakFrameworks,
                    InPublicAdditionalFrameworks,
                    InPublicAdditionalShadowFiles,
                    InPublicAdditionalBundleResources,
                    InPublicIncludePathModuleNames,
                    InPublicDependencyModuleNames,
                    InPublicDelayLoadDLLs,
                    InPrivateIncludePaths,
                    InPrivateIncludePathModuleNames,
                    InPrivateDependencyModuleNames,
                    InCircularlyReferencedDependentModules,
                    InDynamicallyLoadedModuleNames,
                    InPlatformSpecificDynamicallyLoadedModuleNames)
        {
            IntelliSenseGatherer = InIntelliSenseGatherer;

            CategorizeSourceFiles(InSourceFiles, SourceFilesFound);
            if (bInBuildSourceFiles)
            {
                CategorizeSourceFiles(InSourceFiles, SourceFilesToBuild);
            }

            Definitions = HashSetFromOptionalEnumerableStringParameter(InDefinitions);
            foreach (var Def in Definitions)
            {
                Log.TraceVerbose("Compile Env {0}: {1}", Name, Def);
            }
            OptimizeCode                           = InOptimizeCode;
            bAllowSharedPCH                        = InAllowSharedPCH;
            SharedPCHHeaderFile                    = InSharedPCHHeaderFile;
            bUseRTTI                               = InUseRTTI;
            bEnableBufferSecurityChecks            = InEnableBufferSecurityChecks;
            bFasterWithoutUnity                    = InFasterWithoutUnity;
            MinFilesUsingPrecompiledHeaderOverride = InMinFilesUsingPrecompiledHeaderOverride;
            bEnableExceptions                      = InEnableExceptions;
        }
Exemple #19
0
 /**
  * Gathers and binds binaries for this module and all of it's dependent modules
  *
  * @param	Target				The target we are currently building
  * @param	Binaries			Dictionary of all binaries we've gathered so far
  * @param	ExecutableBinary	The binary for the target's main executable (used only when linking monolithically)
  * @param	bBuildOnlyModules	True to build only specific modules, false for all
  * @param	ModulesToBuild		The specific modules to build
  */
 public virtual void RecursivelyProcessUnboundModules(STBuildTarget Target, ref Dictionary<string, STBuildBinary> Binaries, STBuildBinary ExecutableBinary)
 {
 }
Exemple #20
0
        public static FileItem CachePCHUsageForModuleSourceFile(STBuildTarget Target, CPPEnvironment ModuleCompileEnvironment, FileItem CPPFile)
        {
            if (!CPPFile.bExists)
            {
                throw new BuildException("Required source file not found: " + CPPFile.AbsolutePath);
            }

            var PCHCacheTimerStart = DateTime.UtcNow;

            var BuildPlatform = STBuildPlatform.GetBuildPlatformForCPPTargetPlatform(ModuleCompileEnvironment.Config.Target.Platform);
            var IncludePathsToSearch = ModuleCompileEnvironment.Config.CPPIncludeInfo.GetIncludesPathsToSearch(CPPFile);

            // Store the module compile environment along with the .cpp file.  This is so that we can use it later on when looking
            // for header dependencies
            CPPFile.CachedCPPIncludeInfo = ModuleCompileEnvironment.Config.CPPIncludeInfo;

            var PCHFile = CachePCHUsageForCPPFile(Target, CPPFile, BuildPlatform, IncludePathsToSearch, ModuleCompileEnvironment.Config.CPPIncludeInfo.IncludeFileSearchDictionary);

            if (BuildConfiguration.bPrintPerformanceInfo)
            {
                var PCHCacheTime = (DateTime.UtcNow - PCHCacheTimerStart).TotalSeconds;
                TotalPCHCacheTime += PCHCacheTime;
            }

            return PCHFile;
        }
Exemple #21
0
 public abstract CPPOutput CompileCPPFiles(STBuildTarget Target, CPPEnvironment CompileEnvironment, List<FileItem> SourceFiles, string ModuleName);
Exemple #22
0
        /// <summary>
        /// Determines where generated code files will be stored for this module
        /// </summary>
        /// <param name="ModuleDirectory">Module's base directory</param>
        /// <param name="ModuleName">Name of module</param>
        /// <returns></returns>
        public static string GetGeneratedCodeDirectoryForModule(STBuildTarget Target, string ModuleDirectory, string ModuleName)
        {
            string BaseDirectory = null;
            if ((Target.ShouldCompileMonolithic() || Target.TargetType == TargetRules.TargetType.Program) &&
                (!STBuildTool.BuildingRocket()) &&
                (!STBuildTool.RunningRocket() || Utils.IsFileUnderDirectory(ModuleDirectory, STBuildTool.GetUProjectPath())))
            {
                // Monolithic configurations and programs have their intermediate headers stored under their
                // respective project folders with the exception of rocket which always stores engine modules in the engine folder.
                string RootDirectory = STBuildTool.GetUProjectPath();
                if (String.IsNullOrEmpty(RootDirectory))
                {
                    // Intermediates under Engine intermediate folder (program name will be appended later)
                    RootDirectory = Path.GetFullPath(BuildConfiguration.RelativeEnginePath);
                }
                BaseDirectory = Path.Combine(RootDirectory, BuildConfiguration.PlatformIntermediateFolder, Target.GetTargetName(), "Inc");
            }
            else if (Plugins.IsPluginModule(ModuleName))
            {
                // Plugin module
                string PluginIntermediateIncPath;
                {
                    PluginInfo Plugin = Plugins.GetPluginInfoForModule(ModuleName);
                    if (Plugin.LoadedFrom == PluginInfo.LoadedFromType.Engine)
                    {
                        // Plugin folder is in the engine directory
                        PluginIntermediateIncPath = Path.GetFullPath(Path.Combine(BuildConfiguration.RelativeEnginePath, BuildConfiguration.PlatformIntermediateFolder));
                    }
                    else
                    {
                        // Plugin folder is in the project directory
                        PluginIntermediateIncPath = Path.GetFullPath(Path.Combine(Target.ProjectDirectory, BuildConfiguration.PlatformIntermediateFolder));
                    }
                    PluginIntermediateIncPath = Path.Combine(PluginIntermediateIncPath, "Inc", "Plugins");
                }
                BaseDirectory = PluginIntermediateIncPath;
            }
            else
            {
                var AllProjectFolders = STBuildTarget.DiscoverAllGameFolders();		// @todo fastubt: This will be called again and again for every UObject module (80+)
                BaseDirectory = AllProjectFolders.Find(ProjectFolder => Utils.IsFileUnderDirectory(ModuleDirectory, ProjectFolder));
                if (BaseDirectory == null)
                {
                    // Must be an engine module or program module
                    BaseDirectory = ProjectFileGenerator.EngineRelativePath;
                }

                BaseDirectory = Path.GetFullPath(Path.Combine(BaseDirectory, BuildConfiguration.PlatformIntermediateFolder, "Inc"));
            }

            // Construct the intermediate path.
            var GeneratedCodeDirectory = Path.Combine(BaseDirectory, ModuleName);
            return GeneratedCodeDirectory + Path.DirectorySeparatorChar;
        }
Exemple #23
0
 public virtual void FixBundleBinariesPaths(STBuildTarget Target, List<STBuildBinary> Binaries)
 {
 }
Exemple #24
0
        public override void RecursivelyAddIncludePathModules(STBuildTarget Target, bool bPublicIncludesOnly)
        {
            var AllIncludePathModuleNames = new List<string>();
            AllIncludePathModuleNames.AddRange(PublicIncludePathModuleNames);
            if (!bPublicIncludesOnly)
            {
                AllIncludePathModuleNames.AddRange(PrivateIncludePathModuleNames);
            }
            foreach (var IncludePathModuleName in AllIncludePathModuleNames)
            {
                var IncludePathModule = Target.FindOrCreateModuleByName(IncludePathModuleName);

                // No need to do anything here.  We just want to make sure that we've instantiated our representation of the
                // module so that we can find it later when processing include path module names.  Unlike actual dependency
                // modules, these include path modules may never be "bound" (have Binary or bIncludedInTarget member variables set)

                // We'll also need to make sure we know about all dependent public include path modules, too!
                IncludePathModule.RecursivelyAddIncludePathModules(Target, bPublicIncludesOnly: true);
            }
        }
Exemple #25
0
        protected void AddPrerequisiteSourceFile(STBuildTarget Target, ISTBuildPlatform BuildPlatform, CPPEnvironment CompileEnvironment, FileItem SourceFile, List<FileItem> PrerequisiteItems)
        {
            PrerequisiteItems.Add(SourceFile);

            var RemoteThis = this as RemoteToolChain;
            bool bAllowUploading = RemoteThis != null && BuildHostPlatform.Current.Platform != STTargetPlatform.Mac;	// Don't use remote features when compiling from a Mac
            if (bAllowUploading)
            {
                RemoteThis.QueueFileForBatchUpload(SourceFile);
            }

            if (!BuildConfiguration.bUseExperimentalFastBuildIteration)	// In fast build iteration mode, we'll gather includes later on
            {
                // @todo fastubt: What if one of the prerequisite files has become missing since it was updated in our cache? (usually, because a coder eliminated the source file)
                //		-> Two CASES:
                //				1) NOT WORKING: Non-unity file went away (SourceFile in this context).  That seems like an existing old use case.  Compile params or Response file should have changed?
                //				2) WORKING: Indirect file went away (unity'd original source file or include).  This would return a file that no longer exists and adds to the prerequiteitems list
                var IncludedFileList = CPPEnvironment.FindAndCacheAllIncludedFiles(Target, SourceFile, BuildPlatform, CompileEnvironment.Config.CPPIncludeInfo, bOnlyCachedDependencies: BuildConfiguration.bUseExperimentalFastDependencyScan);
                foreach (FileItem IncludedFile in IncludedFileList)
                {
                    PrerequisiteItems.Add(IncludedFile);

                    if (bAllowUploading &&
                        !BuildConfiguration.bUseExperimentalFastDependencyScan)	// With fast dependency scanning, we will not have an exhaustive list of dependencies here.  We rely on PostCodeGeneration() to upload these files.
                    {
                        RemoteThis.QueueFileForBatchUpload(IncludedFile);
                    }
                }
            }
        }
Exemple #26
0
        public override void RecursivelyProcessUnboundModules(STBuildTarget Target, ref Dictionary<string, STBuildBinary> Binaries, STBuildBinary ExecutableBinary)
        {
            try
            {
                // Make sure this module is bound to a binary
                if (!bIncludedInTarget)
                {
                    throw new BuildException("Module '{0}' should already have been bound to a binary!", Name);
                }

                var AllModuleNames = new List<string>();
                AllModuleNames.AddRange(PrivateDependencyModuleNames);
                AllModuleNames.AddRange(PublicDependencyModuleNames);
                AllModuleNames.AddRange(DynamicallyLoadedModuleNames);
                AllModuleNames.AddRange(PlatformSpecificDynamicallyLoadedModuleNames);

                foreach (var DependencyName in AllModuleNames)
                {
                    var DependencyModule = Target.FindOrCreateModuleByName(DependencyName);

                    // Skip modules that are included with the target (externals)
                    if (!DependencyModule.bIncludedInTarget)
                    {
                        if (!Binaries.ContainsKey(DependencyModule.Name))
                        {
                            STBuildBinary BinaryToBindTo;
                            if (Target.ShouldCompileMonolithic())
                            {
                                // When linking monolithically, any unbound modules will be linked into the main executable
                                BinaryToBindTo = ExecutableBinary;
                            }
                            else
                            {
                                // Is this a plugin module?
                                var PluginInfo = Plugins.GetPluginInfoForModule(DependencyName);

                                string[] OutputFilePaths = Target.MakeBinaryPaths(DependencyModule.Name, Target.GetAppName() + "-" + DependencyModule.Name, STBuildBinaryType.DynamicLinkLibrary, Target.TargetType, PluginInfo, "");

                                // If it's an engine module, output intermediates to the engine intermediates directory.
                                string IntermediateDirectory = Binary.Config.IntermediateDirectory;
                                if (IntermediateDirectory != Target.EngineIntermediateDirectory && Path.GetFullPath(DependencyModule.ModuleDirectory).StartsWith(Path.GetFullPath(BuildConfiguration.RelativeEnginePath)))
                                {
                                    IntermediateDirectory = Target.EngineIntermediateDirectory;
                                }

                                // When using modular linkage, unbound modules will be linked into their own DLL files
                                STBuildBinaryConfiguration Config = new STBuildBinaryConfiguration(InType: STBuildBinaryType.DynamicLinkLibrary,
                                                                                                    InOutputFilePaths: OutputFilePaths,
                                                                                                    InIntermediateDirectory: IntermediateDirectory,
                                                                                                    bInAllowExports: true,
                                                                                                    InModuleNames: new List<string> { DependencyModule.Name },
                                                                                                    InTargetName: Target.GetAppName(),
                                                                                                    bInIsCrossTarget: PlatformSpecificDynamicallyLoadedModuleNames.Contains(DependencyName) && !DynamicallyLoadedModuleNames.Contains(DependencyName),
                                                                                                    InTargetConfiguration: Target.Configuration,
                                                                                                    bInCompileMonolithic: Target.ShouldCompileMonolithic());

                                // Fix up the binary path if this is module specifies an alternate output directory
                                for (int Index = 0; Index < Config.OutputFilePaths.Length; Index++)
                                {
                                    Config.OutputFilePaths[Index] = DependencyModule.FixupOutputPath(Config.OutputFilePaths[Index]);
                                }

                                BinaryToBindTo = new STBuildBinaryCPP(Target, Config);
                            }

                            Binaries[DependencyModule.Name] = BinaryToBindTo;

                            // Bind this module
                            DependencyModule.Binary = BinaryToBindTo;
                            DependencyModule.bIncludedInTarget = true;

                            // Also add binaries for this module's dependencies
                            DependencyModule.RecursivelyProcessUnboundModules(Target, ref Binaries, ExecutableBinary);
                        }
                    }

                    if (Target.ShouldCompileMonolithic() == false)
                    {
                        // Check to see if there is a circular relationship between the module and it's referencer
                        if (DependencyModule.Binary != null)
                        {
                            if (CircularlyReferencedDependentModules.Contains(DependencyName))
                            {
                                DependencyModule.Binary.SetCreateImportLibrarySeparately(true);
                            }
                        }
                    }
                }

                // Also make sure module entries are created for any module that is pulled in as an "include path" module.
                // These modules are never linked in unless they were referenced as an actual dependency of a different module,
                // but we still need to keep track of them so that we can find their include paths when setting up our
                // module's include paths.
                RecursivelyAddIncludePathModules(Target, bPublicIncludesOnly: false);
            }
            catch (System.Exception ex)
            {
                throw new ModuleProcessingException(this, ex);
            }
        }
Exemple #27
0
 /// <summary>
 /// Create an instance of the class with the given configuration data
 /// </summary>
 /// <param name="InConfig">The build binary configuration to initialize the class with</param>
 public STBuildBinary(STBuildTarget InTarget, STBuildBinaryConfiguration InConfig)
 {
     Debug.Assert(InConfig.OutputFilePath != null && InConfig.IntermediateDirectory != null);
     Target = InTarget;
     Config = InConfig;
 }
Exemple #28
0
        private static FileItem CachePCHUsageForCPPFile(STBuildTarget Target, FileItem CPPFile, ISTBuildPlatform BuildPlatform, List<string> IncludePathsToSearch, Dictionary<string, FileItem> IncludeFileSearchDictionary)
        {
            // @todo fastubt: We don't really need to scan every file looking for PCH headers, just need one.  The rest is just for error checking.
            // @todo fastubt: We don't need all of the direct includes either.  We just need the first, unless we want to check for errors.
            bool HasUObjects;
            List<DependencyInclude> DirectIncludeFilenames = CPPEnvironment.GetDirectIncludeDependencies(Target, CPPFile, BuildPlatform, bOnlyCachedDependencies: false, HasUObjects: out HasUObjects);
            if (BuildConfiguration.bPrintDebugInfo)
            {
                Log.TraceVerbose("Found direct includes for {0}: {1}", Path.GetFileName(CPPFile.AbsolutePath), string.Join(", ", DirectIncludeFilenames.Select(F => F.IncludeName)));
            }

            if (DirectIncludeFilenames.Count == 0)
            {
                return null;
            }

            var FirstInclude = DirectIncludeFilenames[0];

            // The pch header should always be the first include in the source file.
            // NOTE: This is not an absolute path.  This is just the literal include string from the source file!
            CPPFile.PCHHeaderNameInCode = FirstInclude.IncludeName;

            // Resolve the PCH header to an absolute path.
            // Check NullOrEmpty here because if the file could not be resolved we need to throw an exception
            if (!string.IsNullOrEmpty(FirstInclude.IncludeResolvedName) &&
                // ignore any preexisting resolve cache if we are not configured to use it.
                BuildConfiguration.bUseIncludeDependencyResolveCache &&
                // if we are testing the resolve cache, we force UBT to resolve every time to look for conflicts
                !BuildConfiguration.bTestIncludeDependencyResolveCache)
            {
                CPPFile.PrecompiledHeaderIncludeFilename = FirstInclude.IncludeResolvedName;
                return FileItem.GetItemByFullPath(CPPFile.PrecompiledHeaderIncludeFilename);
            }

            // search the include paths to resolve the file.
            FileItem PrecompiledHeaderIncludeFile = CPPEnvironment.FindIncludedFile(CPPFile.PCHHeaderNameInCode, !BuildConfiguration.bCheckExternalHeadersForModification, IncludePathsToSearch, IncludeFileSearchDictionary);
            if (PrecompiledHeaderIncludeFile == null)
            {
                throw new BuildException("The first include statement in source file '{0}' is trying to include the file '{1}' as the precompiled header, but that file could not be located in any of the module's include search paths.", CPPFile.AbsolutePath, CPPFile.PCHHeaderNameInCode);
            }

            CPPEnvironment.IncludeDependencyCache[Target].CacheResolvedIncludeFullPath(CPPFile, 0, PrecompiledHeaderIncludeFile.AbsolutePath);
            CPPFile.PrecompiledHeaderIncludeFilename = PrecompiledHeaderIncludeFile.AbsolutePath;

            return PrecompiledHeaderIncludeFile;
        }
Exemple #29
0
        /// <summary>
        /// Checks if the editor is currently running and this is a hot-reload
        /// </summary>
        /// <param name="ResetPlatform"></param>
        /// <param name="ResetConfiguration"></param>
        /// <param name="Target"></param>
        /// <returns></returns>
        private static bool ShouldDoHotReload(STBuildTarget Target)
        {
            if (STBuildTool.CommandLineContains("-NoHotReloadFromIDE"))
            {
                // Hot reload disabled through command line, possibly running from UAT
                return false;
            }

            bool bIsRunning = false;
            if (!ProjectFileGenerator.bGenerateProjectFiles && !STBuildConfiguration.bGenerateManifest && Target.TargetType == TargetRules.TargetType.Editor)
            {
                var EditorProcessFilenames = STBuildTarget.MakeBinaryPaths("Launcher", "UE4Editor", Target.Platform, Target.Configuration, STBuildBinaryType.Executable, null, null, "UE4Editor");
                if (EditorProcessFilenames.Length != 1)
                {
                    throw new BuildException("ShouldDoHotReload cannot handle multiple binaries returning from STBuildTarget.MakeBinaryPaths");
                }

                var EditorProcessFilename = EditorProcessFilenames[0];
                var EditorProcessName = Path.GetFileNameWithoutExtension(EditorProcessFilename);
                var EditorProcesses = BuildHostPlatform.Current.GetProcessesByName(EditorProcessName);
                var BinariesPath = Path.GetFullPath(Path.GetDirectoryName(EditorProcessFilename));
                var PerProjectBinariesPath = Path.Combine(Target.ProjectDirectory, BinariesPath.Substring(BinariesPath.LastIndexOf("Binaries")));
                bIsRunning = EditorProcesses.FirstOrDefault(EditorProc =>
                {
                    if (!Path.GetFullPath(EditorProc.Filename).StartsWith(BinariesPath, StringComparison.InvariantCultureIgnoreCase))
                    {
                        return false;
                    }

                    if (PerProjectBinariesPath.Equals(BinariesPath, StringComparison.InvariantCultureIgnoreCase))
                    {
                        return false;
                    }

                    var Modules = BuildHostPlatform.Current.GetProcessModules(EditorProc.PID, EditorProc.Filename);
                    if (!Modules.Any(Module => Module.StartsWith(PerProjectBinariesPath)))
                    {
                        return false;
                    }

                    return true;
                }) != default(BuildHostPlatform.ProcessInfo);
            }
            return bIsRunning;
        }
Exemple #30
0
 public STBuildExternalModule(
     STBuildTarget InTarget,
     STBuildModuleType InType,
     string InName,
     string InModuleDirectory,
     string InOutputDirectory,
     bool? InIsRedistributableOverride,
     IEnumerable<string> InPublicDefinitions = null,
     IEnumerable<string> InPublicIncludePaths = null,
     IEnumerable<string> InPublicSystemIncludePaths = null,
     IEnumerable<string> InPublicLibraryPaths = null,
     IEnumerable<string> InPublicAdditionalLibraries = null,
     IEnumerable<string> InPublicFrameworks = null,
     IEnumerable<string> InPublicWeakFrameworks = null,
     IEnumerable<STBuildFramework> InPublicAdditionalFrameworks = null,
     IEnumerable<string> InPublicAdditionalShadowFiles = null,
     IEnumerable<STBuildBundleResource> InPublicAdditionalBundleResources = null,
     IEnumerable<string> InPublicDependencyModuleNames = null,
     IEnumerable<string> InPublicDelayLoadDLLs = null		// Delay loaded DLLs that should be setup when including this module
     )
     : base(InTarget: InTarget,
         InType: InType,
         InName: InName,
         InModuleDirectory: InModuleDirectory,
         InOutputDirectory: InOutputDirectory,
         InIsRedistributableOverride: InIsRedistributableOverride,
         InPublicDefinitions: InPublicDefinitions,
         InPublicIncludePaths: InPublicIncludePaths,
         InPublicSystemIncludePaths: InPublicSystemIncludePaths,
         InPublicLibraryPaths: InPublicLibraryPaths,
         InPublicAdditionalLibraries: InPublicAdditionalLibraries,
         InPublicFrameworks: InPublicFrameworks,
         InPublicWeakFrameworks: InPublicWeakFrameworks,
         InPublicAdditionalFrameworks: InPublicAdditionalFrameworks,
         InPublicAdditionalShadowFiles: InPublicAdditionalShadowFiles,
         InPublicAdditionalBundleResources: InPublicAdditionalBundleResources,
         InPublicDependencyModuleNames: InPublicDependencyModuleNames,
         InPublicDelayLoadDLLs: InPublicDelayLoadDLLs)
 {
     bIncludedInTarget = true;
 }