/// <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 ubtmake: 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 ubtmake: 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); }
/// <summary> /// Loads the cache from disk /// </summary> /// <param name="Cache">The file to load</param> /// <returns>The loaded instance</returns> public static FlatCPPIncludeDependencyCache Load(FileReference BackingFile) { FlatCPPIncludeDependencyCache Result = null; try { string CacheBuildMutexPath = BackingFile.FullName + ".buildmutex"; // If the .buildmutex file for the cache is present, it means that something went wrong between loading // and saving the cache last time (most likely the UBT process being terminated), so we don't want to load // it. if (!File.Exists(CacheBuildMutexPath)) { using (File.Create(CacheBuildMutexPath)) { } using (BinaryReader Reader = new BinaryReader(new FileStream(BackingFile.FullName, FileMode.Open, FileAccess.Read))) { // @todo ubtmake: 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 ubtmake: 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) if (Reader.ReadInt32() == FileSignature) { Result = Deserialize(Reader); } } } } catch (Exception Ex) { Console.Error.WriteLine("Failed to read FlatCPPIncludeDependencyCache: {0}", Ex.Message); BackingFile.Delete(); } return(Result); }
/// <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(UEBuildTarget 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)); }
/// <summary> /// Deserialize the dependency cache from a binary reader /// </summary> /// <param name="Reader">Reader for the cache data</param> /// <returns>New dependency cache object</returns> static FlatCPPIncludeDependencyCache Deserialize(BinaryReader Reader) { FlatCPPIncludeDependencyCache Cache = new FlatCPPIncludeDependencyCache(Reader.ReadFileReference()); // Create the dependency map int NumDependencyMapEntries = Reader.ReadInt32(); Cache.DependencyMap = new Dictionary <FileReference, FlatCPPIncludeDependencyInfo>(NumDependencyMapEntries); // Read all the dependency map entries List <FileReference> UniqueFiles = new List <FileReference>(NumDependencyMapEntries * 2); for (int Idx = 0; Idx < NumDependencyMapEntries; Idx++) { FileReference File = Reader.ReadFileReference(); FlatCPPIncludeDependencyInfo Info = new FlatCPPIncludeDependencyInfo(); // Read the includes int NumIncludes = Reader.ReadInt32(); Info.Includes = new List <FileReference>(NumIncludes); for (int IncludeIdx = 0; IncludeIdx < NumIncludes; IncludeIdx++) { Info.Includes.Add(Reader.ReadFileReference(UniqueFiles)); } // Add it to the map Cache.DependencyMap.Add(File, Info); } return(Cache); }
/// <summary> /// Loads the cache from disk /// </summary> /// <param name="BackingFile">The file to read from</param> /// <param name="Cache">The loaded cache</param> /// <returns>True if successful</returns> public static bool TryRead(FileReference BackingFile, out FlatCPPIncludeDependencyCache Cache) { if (!FileReference.Exists(BackingFile)) { Cache = null; return(false); } if (UnrealBuildTool.bPrintPerformanceInfo) { Log.TraceInformation("Loading existing FlatCPPIncludeDependencyCache: " + BackingFile.FullName); } DateTime TimerStartTime = DateTime.UtcNow; try { // If the .buildmutex file for the cache is present, it means that something went wrong between loading // and saving the cache last time (most likely the UBT process being terminated), so we don't want to load // it. string CacheBuildMutexPath = BackingFile.FullName + ".buildmutex"; if (File.Exists(CacheBuildMutexPath)) { Cache = null; return(false); } File.Create(CacheBuildMutexPath).Close(); using (BinaryReader Reader = new BinaryReader(new FileStream(BackingFile.FullName, FileMode.Open, FileAccess.Read))) { // @todo ubtmake: 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 ubtmake: 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) if (Reader.ReadInt32() != FileSignature) { Cache = null; return(false); } Cache = Deserialize(Reader); if (UnrealBuildTool.bPrintPerformanceInfo) { TimeSpan TimerDuration = DateTime.UtcNow - TimerStartTime; Log.TraceInformation("Loading FlatCPPIncludeDependencyCache took " + TimerDuration.TotalSeconds + "s"); } return(true); } } catch (Exception Ex) { Console.Error.WriteLine("Failed to read FlatCPPIncludeDependencyCache: {0}", Ex.Message); FileReference.Delete(BackingFile); Cache = null; return(false); } }
/// <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(UEBuildTarget 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); } } bool bIsBuilding = (ProjectFileGenerator.bGenerateProjectFiles == false) && (BuildConfiguration.bXGEExport == false) && (UEBuildConfiguration.bGenerateManifest == false) && (UEBuildConfiguration.bGenerateExternalFileList == false) && (UEBuildConfiguration.bCleanProject == false); if (bIsBuilding && !UnrealBuildTool.bNeedsFullCPPIncludeRescan) { UnrealBuildTool.bNeedsFullCPPIncludeRescan = true; Log.TraceInformation("Performing full C++ include scan (no include cache file)"); } // Fall back to a clean cache on error or non-existence. return(new FlatCPPIncludeDependencyCache(Cache)); }
/// <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 { string CacheBuildMutexPath = Cache.AbsolutePath + ".buildmutex"; // If the .buildmutex file for the cache is present, it means that something went wrong between loading // and saving the cache last time (most likely the UBT process being terminated), so we don't want to load // it. if (!File.Exists(CacheBuildMutexPath)) { using (File.Create(CacheBuildMutexPath)) { } using (FileStream Stream = new FileStream(Cache.AbsolutePath, FileMode.Open, FileAccess.Read)) { // @todo ubtmake: 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 ubtmake: 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); }
/// <summary> /// Deserialize the dependency cache from a binary reader /// </summary> /// <param name="Reader">Reader for the cache data</param> /// <returns>New dependency cache object</returns> static FlatCPPIncludeDependencyCache Deserialize(BinaryReader Reader) { FlatCPPIncludeDependencyCache Cache = new FlatCPPIncludeDependencyCache(Reader.ReadFileReference()); // Create the dependency map int NumDependencyMapEntries = Reader.ReadInt32(); Cache.DependencyMap = new Dictionary<FileReference, FlatCPPIncludeDependencyInfo>(NumDependencyMapEntries); // Read all the dependency map entries List<FileReference> UniqueFiles = new List<FileReference>(NumDependencyMapEntries * 2); for (int Idx = 0; Idx < NumDependencyMapEntries; Idx++) { FileReference File = Reader.ReadFileReference(); FlatCPPIncludeDependencyInfo Info = new FlatCPPIncludeDependencyInfo(); // Read the PCH name Info.PCHName = Reader.ReadFileReference(UniqueFiles); // Read the includes int NumIncludes = Reader.ReadInt32(); Info.Includes = new List<FileReference>(NumIncludes); for (int IncludeIdx = 0; IncludeIdx < NumIncludes; IncludeIdx++) { Info.Includes.Add(Reader.ReadFileReference(UniqueFiles)); } // Add it to the map Cache.DependencyMap.Add(File, Info); } return Cache; }