示例#1
0
 public PrecompileHeaderEnvironment(string InitModuleName, string InitPCHHeaderNameInCode, FileItem InitPrecompiledHeaderIncludeFilename, CPPCLRMode InitCLRMode, ModuleRules.CodeOptimization InitOptimizeCode)
 {
     ModuleName = InitModuleName;
     PCHHeaderNameInCode = InitPCHHeaderNameInCode;
     PrecompiledHeaderIncludeFilename = InitPrecompiledHeaderIncludeFilename;
     CLRMode = InitCLRMode;
     OptimizeCode = InitOptimizeCode;
 }
示例#2
0
 /**
  * Constructor
  *
  * @param	Cache	File associated with this cache
  */
 protected DependencyCache(FileItem Cache)
 {
     CacheCreateDate = DateTimeOffset.Now;
     CacheUpdateDate = DateTimeOffset.Now;
     CachePath = Cache.AbsolutePath;
     DependencyMap = new Dictionary<string, DependencyInfo>(StringComparer.InvariantCultureIgnoreCase);
     bIsDirty = false;
     CreateFileExistsInfo();
 }
示例#3
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);
        }
示例#4
0
        /// <summary>
        /// Get the name of the response file for the current linker environment and output file
        /// </summary>
        /// <param name="LinkEnvironment"></param>
        /// <param name="OutputFile"></param>
        /// <returns></returns>
        public static string GetResponseFileName(LinkEnvironment LinkEnvironment, FileItem OutputFile)
        {
            // Construct a relative path for the intermediate response file
            string ResponseFileName = Path.Combine(LinkEnvironment.Config.IntermediateDirectory, Path.GetFileName(OutputFile.AbsolutePath) + ".response");
            if (STBuildTool.HasUProjectFile())
            {
                // If this is the uproject being built, redirect the intermediate
                if (Utils.IsFileUnderDirectory(OutputFile.AbsolutePath, STBuildTool.GetUProjectPath()))
                {
                    ResponseFileName = Path.Combine(
                        STBuildTool.GetUProjectPath(),
                        BuildConfiguration.PlatformIntermediateFolder,
                        Path.GetFileNameWithoutExtension(STBuildTool.GetUProjectFile()),
                        LinkEnvironment.Config.Target.Configuration.ToString(),
                        Path.GetFileName(OutputFile.AbsolutePath) + ".response");
                }
            }
            // Convert the relative path to an absolute path
            ResponseFileName = Path.GetFullPath(ResponseFileName);

            return ResponseFileName;
        }
示例#5
0
 /// <summary>
 /// Checks if the specified file is a C++ source header file (e.g., .h or .inl)
 /// </summary>
 /// <param name="FileItem">The file to check</param>
 /// <returns>True if this is a C++ source file</returns>
 private static bool IsCPPIncludeFile(FileItem FileItem)
 {
     return (FileItem.AbsolutePath.EndsWith(".h", StringComparison.InvariantCultureIgnoreCase) ||
             FileItem.AbsolutePath.EndsWith(".inl", StringComparison.InvariantCultureIgnoreCase));
 }
示例#6
0
 /// <summary>
 /// Checks if the specified file is a C++ resource file (e.g., .rc)
 /// </summary>
 /// <param name="FileItem">The file to check</param>
 /// <returns>True if this is a C++ source file</returns>
 private static bool IsCPPResourceFile(FileItem FileItem)
 {
     return (FileItem.AbsolutePath.EndsWith(".rc", StringComparison.InvariantCultureIgnoreCase));
 }
示例#7
0
 /// <summary>
 /// Checks if the specified file is a C++ source file
 /// </summary>
 /// <param name="FileItem">The file to check</param>
 /// <returns>True if this is a C++ source file</returns>
 private static bool IsCPPFile(FileItem FileItem)
 {
     return IsCPPImplementationFile(FileItem) || IsCPPIncludeFile(FileItem) || IsCPPResourceFile(FileItem);
 }
示例#8
0
 /// <summary>
 /// Checks if the specified file is a C++ source implementation file (e.g., .cpp)
 /// </summary>
 /// <param name="FileItem">The file to check</param>
 /// <returns>True if this is a C++ source file</returns>
 private static bool IsCPPImplementationFile(FileItem FileItem)
 {
     return (FileItem.AbsolutePath.EndsWith(".cpp", StringComparison.InvariantCultureIgnoreCase) ||
             FileItem.AbsolutePath.EndsWith(".c", StringComparison.InvariantCultureIgnoreCase) ||
             FileItem.AbsolutePath.EndsWith(".mm", StringComparison.InvariantCultureIgnoreCase));
 }
示例#9
0
        private PrecompileHeaderEnvironment ApplySharedPCH(CPPEnvironment GlobalCompileEnvironment, CPPEnvironment CompileEnvironment, CPPEnvironment ModuleCompileEnvironment, List<FileItem> CPPFiles, ref FileItem SharedPCHHeaderFile)
        {
            // Check to see if we have a PCH header already setup that we can use
            var SharedPCHHeaderFileCopy = SharedPCHHeaderFile;
            var SharedPCHEnvironment = GlobalCompileEnvironment.SharedPCHEnvironments.Find(Env => Env.PrecompiledHeaderIncludeFilename == SharedPCHHeaderFileCopy);
            if (SharedPCHEnvironment == null)
            {
                return null;
            }

            // Don't mix CLR modes
            if (SharedPCHEnvironment.CLRMode != ModuleCompileEnvironment.Config.CLRMode)
            {
                Log.TraceVerbose("Module {0} cannot use existing Shared PCH '{1}' (from module '{2}') because CLR modes don't match", Name, SharedPCHEnvironment.PrecompiledHeaderIncludeFilename.AbsolutePath, SharedPCHEnvironment.ModuleName);
                SharedPCHHeaderFile = null;
                return null;
            }

            // Don't mix non-optimized code with optimized code (PCHs won't be compatible)
            var SharedPCHCodeOptimization = SharedPCHEnvironment.OptimizeCode;
            var ModuleCodeOptimization = ModuleCompileEnvironment.Config.OptimizeCode;

            if (CompileEnvironment.Config.Target.Configuration != CPPTargetConfiguration.Debug)
            {
                if (SharedPCHCodeOptimization == ModuleRules.CodeOptimization.InNonDebugBuilds)
                {
                    SharedPCHCodeOptimization = ModuleRules.CodeOptimization.Always;
                }

                if (ModuleCodeOptimization == ModuleRules.CodeOptimization.InNonDebugBuilds)
                {
                    ModuleCodeOptimization = ModuleRules.CodeOptimization.Always;
                }
            }

            if (SharedPCHCodeOptimization != ModuleCodeOptimization)
            {
                Log.TraceVerbose("Module {0} cannot use existing Shared PCH '{1}' (from module '{2}') because optimization levels don't match", Name, SharedPCHEnvironment.PrecompiledHeaderIncludeFilename.AbsolutePath, SharedPCHEnvironment.ModuleName);
                SharedPCHHeaderFile = null;
                return null;
            }

            return SharedPCHEnvironment;
        }
示例#10
0
 /**
  * Update cache with dependencies for the passed in file.
  *
  * @param	File			File to update dependencies for
  * @param	Dependencies	List of dependencies to cache for passed in file
  * @param	HasUObjects		True if this file was found to contain UObject classes or types
  */
 public void SetDependencyInfo(FileItem File, List<DependencyInclude> DirectDependencies, bool HasUObjects)
 {
     DependencyMap[File.AbsolutePath] = new DependencyInfo() { Includes = DirectDependencies, HasUObjects = HasUObjects };
     bIsDirty = true;
 }
示例#11
0
        public FileItem LocalToRemoteFileItem(FileItem LocalFileItem, bool bShouldUpload)
        {
            FileItem RemoteFileItem = null;

            // Look to see if we've already made a remote FileItem for this local FileItem
            if (!CachedRemoteFileItems.TryGetValue(LocalFileItem, out RemoteFileItem))
            {
                // If not, create it now
                string RemoteFilePath = ConvertPath(LocalFileItem.AbsolutePath);
                RemoteFileItem = FileItem.GetRemoteItemByPath(RemoteFilePath, RemoteToolChainPlatform);

                // Is shadowing requested?
                if (bShouldUpload)
                {
                    QueueFileForBatchUpload(LocalFileItem);
                }

                CachedRemoteFileItems.Add(LocalFileItem, RemoteFileItem);
            }

            return RemoteFileItem;
        }
示例#12
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;
        }
 /// <summary>
 /// Constructs a fresh cache, storing the file name that it should be saved as later on
 /// </summary>
 /// <param name="Cache">File name for this cache, usually unique per context (e.g. target)</param>
 protected FlatCPPIncludeDependencyCache(FileItem Cache)
 {
     CacheFileItem = Cache;
     DependencyMap = new Dictionary<string, FlatCPPIncludeDependencyInfo>(StringComparer.InvariantCultureIgnoreCase);	// @todo fastubt: Apparently StringComparer is not very fast on Mono, better to use ToLowerInvariant(), even though it is an extra string copy
 }
示例#14
0
        /** Copy constructor. */
        protected CPPEnvironment(CPPEnvironment InCopyEnvironment)
        {
            PrecompiledHeaderFile = InCopyEnvironment.PrecompiledHeaderFile;
            PrivateAssemblyDependencies.AddRange(InCopyEnvironment.PrivateAssemblyDependencies);
            SharedPCHHeaderFiles.AddRange(InCopyEnvironment.SharedPCHHeaderFiles);
            SharedPCHEnvironments.AddRange(InCopyEnvironment.SharedPCHEnvironments);
            bHackHeaderGenerator = InCopyEnvironment.bHackHeaderGenerator;

            Config = new CPPEnvironmentConfiguration(InCopyEnvironment.Config);
        }
 /// <summary>
 /// Loads the cache from disk
 /// </summary>
 /// <param name="Cache">The file to load</param>
 /// <returns>The loaded instance</returns>
 public static FlatCPPIncludeDependencyCache Load(FileItem Cache)
 {
     FlatCPPIncludeDependencyCache Result = null;
     try
     {
         using (FileStream Stream = new FileStream(Cache.AbsolutePath, FileMode.Open, FileAccess.Read))
         {
             // @todo fastubt: We can store the cache in a cheaper/smaller way using hash file names and indices into included headers, but it might actually slow down load times
             // @todo fastubt: If we can index PCHs here, we can avoid storing all of the PCH's included headers (PCH's action should have been invalidated, so we shouldn't even have to report the PCH's includes as our indirect includes)
             BinaryFormatter Formatter = new BinaryFormatter();
             Result = Formatter.Deserialize(Stream) as FlatCPPIncludeDependencyCache;
             Result.CacheFileItem = Cache;
             Result.bIsDirty = false;
         }
     }
     catch (Exception Ex)
     {
         // Don't bother failing if the file format has changed, simply abort the cache load
         if (Ex.Message.Contains("cannot be converted to type"))	// To catch serialization differences added when we added the DependencyInfo struct
         {
             Console.Error.WriteLine("Failed to read FlatCPPIncludeDependencyCache: {0}", Ex.Message);
         }
     }
     return Result;
 }
示例#16
0
 /// <summary>
 /// Caches the fully resolved path of the include.
 /// TODO: This method should be more tightly coupled with the Resolve step itself so we don't have to reach into the cache externally
 /// using internal details like the list index.
 /// </summary>
 /// <param name="File">The file whose include is being resolved</param>
 /// <param name="DirectlyIncludedFileNameIndex">Index in the resolve list to quickly find the include in question in the existing cache.</param>
 /// <param name="DirectlyIncludedFileNameFullPath">Full path name of the resolve include.</param>
 public void CacheResolvedIncludeFullPath(FileItem File, int DirectlyIncludedFileNameIndex, string DirectlyIncludedFileNameFullPath)
 {
     if (BuildConfiguration.bUseIncludeDependencyResolveCache)
     {
         var Includes = DependencyMap[File.AbsolutePath].Includes;
         var IncludeToResolve = Includes[DirectlyIncludedFileNameIndex];
         if (BuildConfiguration.bTestIncludeDependencyResolveCache)
         {
             // test whether there are resolve conflicts between modules with different include paths.
             if (IncludeToResolve.IncludeResolvedName != null && IncludeToResolve.IncludeResolvedName != DirectlyIncludedFileNameFullPath)
             {
                 throw new BuildException("Found directly included file that resolved differently in different modules. File ({0}) had previously resolved to ({1}) and now resolves to ({2}).",
                     File.AbsolutePath, IncludeToResolve.IncludeResolvedName, DirectlyIncludedFileNameFullPath);
             }
         }
         Includes[DirectlyIncludedFileNameIndex].IncludeResolvedName = DirectlyIncludedFileNameFullPath;
         if (!String.IsNullOrEmpty(DirectlyIncludedFileNameFullPath))
         {
             bIsDirty = true;
         }
     }
 }
示例#17
0
        /// <summary>
        /// Gets information about this file from our dependency cache.  Only returns information if the file has already been 
        /// cached, and the file has not been changed since the last time we updated our cache
        /// </summary>
        /// <param name="File">The file to check</param>
        /// <returns>Information about this dependency, or null if we have nothing cached</returns>
        DependencyInfo? GetCachedDependencyInfo(FileItem File)
        {
            // Check whether File is in cache.
            DependencyInfo DependencyInfo;
            if (DependencyMap.TryGetValue(File.AbsolutePath, out DependencyInfo))
            {
                // File is in cache, now check whether last write time is prior to cache creation time.
                if (File.LastWriteTime < CacheCreateDate)
                {
                    return DependencyInfo;
                }
                else
                {
                    // Remove entry from cache as it's stale.
                    RemoveFileFromCache(File.AbsolutePath);
                    return null;
                }
            }

            return null;
        }
示例#18
0
 /**
  * Determines the full set of actions that must be built to produce an item.
  * @param OutputItem - The item to be built.
  * @param PrerequisiteActions - The actions that must be built and the root action are
  */
 public static void GatherPrerequisiteActions(
     FileItem OutputItem,
     ref HashSet<Action> PrerequisiteActions
     )
 {
     if (OutputItem != null && OutputItem.ProducingAction != null)
     {
         if (!PrerequisiteActions.Contains(OutputItem.ProducingAction))
         {
             PrerequisiteActions.Add(OutputItem.ProducingAction);
             foreach (FileItem PrerequisiteItem in OutputItem.ProducingAction.PrerequisiteItems)
             {
                 GatherPrerequisiteActions(PrerequisiteItem, ref PrerequisiteActions);
             }
         }
     }
 }
示例#19
0
 /**
  * Loads the cache from the passed in file.
  *
  * @param	Cache	File to deserialize from
  */
 public static DependencyCache Load(FileItem Cache)
 {
     DependencyCache Result = null;
     try
     {
         using (FileStream Stream = new FileStream(Cache.AbsolutePath, FileMode.Open, FileAccess.Read))
         {
             BinaryFormatter Formatter = new BinaryFormatter();
             Result = Formatter.Deserialize(Stream) as DependencyCache;
         }
         Result.CreateFileExistsInfo();
         Result.ResetUnresolvedDependencies();
     }
     catch (Exception Ex)
     {
         // Don't bother logging this expected error.
         // It's due to a change in the CacheCreateDate type.
         if (Ex.Message != "Object of type 'System.DateTime' cannot be converted to type 'System.DateTimeOffset'" &&
     Ex.Message != "Object of type 'System.Collections.Generic.Dictionary`2[System.String,System.Collections.Generic.List`1[System.String]]' cannot be converted to type 'System.Collections.Generic.Dictionary`2[System.String,STBuildTool.DependencyInfo]'.")	// To catch serialization differences added when we added the DependencyInfo struct
         {
             Console.Error.WriteLine("Failed to read dependency cache: {0}", Ex.Message);
         }
     }
     return Result;
 }
示例#20
0
        /**
         * Generates debug info for a given executable
         *
         * @param Executable FileItem describing the executable to generate debug info for
         */
        public static FileItem GenerateDebugInfo(FileItem Executable)
        {
            // Make a file item for the source and destination files
            string FullDestPathRoot = Executable.AbsolutePath + ".app.dSYM";
            string FullDestPath = FullDestPathRoot;

            FileItem DestFile;
            if (!Utils.IsRunningOnMono && BuildHostPlatform.Current.Platform != STTargetPlatform.Mac)
            {
                DestFile = FileItem.GetRemoteItemByPath (FullDestPath, STTargetPlatform.IOS);
            }
            else
            {
                DestFile = FileItem.GetItemByPath (FullDestPath);
            }

            // Make the compile action
            Action GenDebugAction = new Action(ActionType.GenerateDebugInfo);
            if (!Utils.IsRunningOnMono)
            {
                GenDebugAction.ActionHandler = new Action.BlockingActionHandler(RPCUtilHelper.RPCActionHandler);
            }

            IOSToolChain Toolchain = STToolChain.GetPlatformToolChain(CPPTargetPlatform.IOS) as IOSToolChain;
            GenDebugAction.WorkingDirectory = Toolchain.GetMacDevSrcRoot();
            GenDebugAction.CommandPath = "sh";

            // note that the source and dest are switched from a copy command
            if (!Utils.IsRunningOnMono && BuildHostPlatform.Current.Platform != STTargetPlatform.Mac)
            {
                GenDebugAction.CommandArguments = string.Format("-c '/usr/bin/dsymutil {0} -o {1}; cd {1}/..; zip -r -y -1 {2}.app.dSYM.zip {2}.app.dSYM'",
                    Executable.AbsolutePath,
                    FullDestPathRoot,
                    Path.GetFileName(Executable.AbsolutePath));
            }
            else
            {
                GenDebugAction.CommandArguments = string.Format("-c '/usr/bin/dsymutil {0} -o {1}'",
                    Executable.AbsolutePath,
                    FullDestPathRoot);
            }

            GenDebugAction.PrerequisiteItems.Add(Executable);
            GenDebugAction.ProducedItems.Add(DestFile);
            GenDebugAction.StatusDescription = GenDebugAction.CommandArguments;// string.Format("Generating debug info for {0}", Path.GetFileName(Executable.AbsolutePath));
            GenDebugAction.bCanExecuteRemotely = false;

            return DestFile;
        }
示例#21
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);
                    }
                }
            }
        }
示例#22
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;
        }
示例#23
0
 public bool GetProducingCommandLine(FileItem File, out string Result)
 {
     return ProducedItemToPreviousActionCommandLine.TryGetValue(File.AbsolutePath.ToUpperInvariant(), out Result);
 }
示例#24
0
        public void QueueFileForBatchUpload(FileItem LocalFileItem)
        {
            // Now, we actually just remember unique directories with any files, and upload all files in them to the remote machine
            // (either via rsync, or RPCUtil acting like rsync)
            string Entry = Path.GetDirectoryName(LocalFileItem.AbsolutePath);
            if (!RsyncDirs.Contains(Entry))
            {
                RsyncDirs.Add(Entry);
            }

            string Ext = Path.GetExtension(LocalFileItem.AbsolutePath);
            if (Ext == "")
            {
                Ext = Path.GetFileName(LocalFileItem.AbsolutePath);
            }
            if (!RsyncExtensions.Contains(Ext))
            {
                RsyncExtensions.Add(Ext);
            }
        }
示例#25
0
        /**
         * Returns the direct dependencies of the specified FileItem if it exists in the cache and if the
         * file has a last write time before the creation time of the cache.
         *
         * The code also keeps track of whether dependencies have been successfully accessed for a given
         * file.
         *
         * @param	File				File to try to find dependencies in cache
         * @param	Result	[out]		List of dependencies if successful, null otherwise
         * @param	HasUObjects			True if the file was found to have UObject classes, otherwise false
         */
        public bool GetCachedDirectDependencies(FileItem File, out List<DependencyInclude> Result, out bool HasUObjects)
        {
            Result = null;
            HasUObjects = false;

            // Check whether File is in cache.
            DependencyInfo? DependencyInfo = GetCachedDependencyInfo(File);
            if (DependencyInfo != null)
            {
                // Check if any of the resolved includes is missing
                foreach (var Include in DependencyInfo.Value.Includes)
                {
                    if (!String.IsNullOrEmpty(Include.IncludeResolvedName))
                    {
                        bool bIncludeExists = false;
                        string FileExistsKey = Include.IncludeResolvedName.ToLowerInvariant();
                        if (FileExistsInfo.TryGetValue(FileExistsKey, out bIncludeExists) == false)
                        {
                            bIncludeExists = System.IO.File.Exists(Include.IncludeResolvedName);
                            FileExistsInfo.Add(FileExistsKey, bIncludeExists);
                        }
                        if (!bIncludeExists)
                        {
                            // Remove entry from cache as it's stale, as well as the include which no longer exists
                            RemoveFileFromCache(Include.IncludeResolvedName);
                            RemoveFileFromCache(File.AbsolutePath);
                            return false;
                        }
                    }
                }
                // Cached version is up to date, return it.
                Result = DependencyInfo.Value.Includes;
                HasUObjects = DependencyInfo.Value.HasUObjects;
                return true;
            }
            // Not in cache.
            else
            {
                return false;
            }
        }
示例#26
0
 public virtual ICollection<FileItem> PostBuild(FileItem Executable, LinkEnvironment ExecutableLinkEnvironment)
 {
     return new List<FileItem>();
 }
示例#27
0
 public void AddFile(FileItem File)
 {
     Files.Add(File);
     TotalLength += File.Info.Length;
 }
示例#28
0
 /// <summary>
 /// Adds a file to the current unity file.  If splitting is required and the total size of the
 /// unity file exceeds the split limit, then a new file is automatically started.
 /// </summary>
 /// <param name="File">The file to add.</param>
 public void AddFile(FileItem File)
 {
     CurrentCollection.AddFile(File);
     if (SplitLength != -1 && CurrentCollection.TotalLength > SplitLength)
     {
         EndCurrentUnityFile();
     }
 }
示例#29
0
 public void SetProducingCommandLine(FileItem File, string CommandLine)
 {
     ProducedItemToPreviousActionCommandLine[File.AbsolutePath.ToUpperInvariant()] = CommandLine;
     bIsDirty = true;
 }