/// <summary> /// Default constructor. /// </summary> public CppCompileEnvironment(CppPlatform Platform, CppConfiguration Configuration, string Architecture, CPPHeaders Headers) { this.Platform = Platform; this.Configuration = Configuration; this.Architecture = Architecture; this.Headers = Headers; }
/// <summary> /// Copy constructor. /// </summary> protected CPPEnvironment(CPPEnvironment InCopyEnvironment) { PrecompiledHeaderFile = InCopyEnvironment.PrecompiledHeaderFile; Headers = InCopyEnvironment.Headers; bHackHeaderGenerator = InCopyEnvironment.bHackHeaderGenerator; Config = new CPPEnvironmentConfiguration(InCopyEnvironment.Config); }
public FileItem CachePCHUsageForCPPFile(FileItem CPPFile, CppIncludePaths IncludePaths, CppPlatform Platform) { // @todo ubtmake: We don't really need to scan every file looking for PCH headers, just need one. The rest is just for error checking. // @todo ubtmake: We don't need all of the direct includes either. We just need the first, unless we want to check for errors. List <DependencyInclude> DirectIncludeFilenames = GetDirectIncludeDependencies(CPPFile, bOnlyCachedDependencies: false); if (UnrealBuildTool.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); } DependencyInclude FirstInclude = DirectIncludeFilenames[0]; // 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 (FirstInclude.IncludeResolvedNameIfSuccessful != null && // ignore any preexisting resolve cache if we are not configured to use it. bUseIncludeDependencyResolveCache && // if we are testing the resolve cache, we force UBT to resolve every time to look for conflicts !bTestIncludeDependencyResolveCache) { CPPFile.PrecompiledHeaderIncludeFilename = FirstInclude.IncludeResolvedNameIfSuccessful; return(FileItem.GetItemByFileReference(CPPFile.PrecompiledHeaderIncludeFilename)); } // search the include paths to resolve the file. string FirstIncludeName = FirstInclude.IncludeName; UEBuildPlatform BuildPlatform = UEBuildPlatform.GetBuildPlatformForCPPTargetPlatform(Platform); // convert back from relative to host path if needed if (!BuildPlatform.UseAbsolutePathsInUnityFiles()) { FirstIncludeName = RemoteExports.UnconvertPath(FirstIncludeName); } FileItem PrecompiledHeaderIncludeFile = CPPHeaders.FindIncludedFile(CPPFile.Reference, FirstIncludeName, IncludePaths); if (PrecompiledHeaderIncludeFile == null) { FirstIncludeName = RemoteExports.UnconvertPath(FirstInclude.IncludeName); 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, FirstIncludeName); } IncludeDependencyCache.CacheResolvedIncludeFullPath(CPPFile, 0, PrecompiledHeaderIncludeFile.Reference, bUseIncludeDependencyResolveCache, bTestIncludeDependencyResolveCache); CPPFile.PrecompiledHeaderIncludeFilename = PrecompiledHeaderIncludeFile.Reference; return(PrecompiledHeaderIncludeFile); }
/// <summary> /// Copy constructor. /// </summary> /// <param name="Other">Environment to copy settings from</param> public CppCompileEnvironment(CppCompileEnvironment Other) { Platform = Other.Platform; Configuration = Other.Configuration; Architecture = Other.Architecture; OutputDirectory = Other.OutputDirectory; PCHOutputDirectory = Other.PCHOutputDirectory; LocalShadowDirectory = Other.LocalShadowDirectory; PrecompiledHeaderIncludeFilename = Other.PrecompiledHeaderIncludeFilename; PrecompiledHeaderAction = Other.PrecompiledHeaderAction; bUseRTTI = Other.bUseRTTI; bUseInlining = Other.bUseInlining; bUseAVX = Other.bUseAVX; bFasterWithoutUnity = Other.bFasterWithoutUnity; MinSourceFilesForUnityBuildOverride = Other.MinSourceFilesForUnityBuildOverride; MinFilesUsingPrecompiledHeaderOverride = Other.MinFilesUsingPrecompiledHeaderOverride; bBuildLocallyWithSNDBS = Other.bBuildLocallyWithSNDBS; bEnableExceptions = Other.bEnableExceptions; bEnableObjCExceptions = Other.bEnableObjCExceptions; bShadowVariableWarningsAsErrors = Other.bShadowVariableWarningsAsErrors; bEnableShadowVariableWarnings = Other.bEnableShadowVariableWarnings; bUndefinedIdentifierWarningsAsErrors = Other.bUndefinedIdentifierWarningsAsErrors; bEnableUndefinedIdentifierWarnings = Other.bEnableUndefinedIdentifierWarnings; bOptimizeCode = Other.bOptimizeCode; bOptimizeForSize = Other.bOptimizeForSize; bCreateDebugInfo = Other.bCreateDebugInfo; bIsBuildingLibrary = Other.bIsBuildingLibrary; bIsBuildingDLL = Other.bIsBuildingDLL; bUseStaticCRT = Other.bUseStaticCRT; bUseDebugCRT = Other.bUseDebugCRT; bOmitFramePointers = Other.bOmitFramePointers; bEnableOSX109Support = Other.bEnableOSX109Support; bUsePDBFiles = Other.bUsePDBFiles; bSupportEditAndContinue = Other.bSupportEditAndContinue; bUseIncrementalLinking = Other.bUseIncrementalLinking; bAllowLTCG = Other.bAllowLTCG; bPGOOptimize = Other.bPGOOptimize; bPGOProfile = Other.bPGOProfile; PGOFilenamePrefix = Other.PGOFilenamePrefix; PGODirectory = Other.PGODirectory; bPrintTimingInfo = Other.bPrintTimingInfo; bAllowRemotelyCompiledPCHs = Other.bAllowRemotelyCompiledPCHs; IncludePaths = new CppIncludePaths(Other.IncludePaths); ForceIncludeFiles.AddRange(Other.ForceIncludeFiles); Definitions.AddRange(Other.Definitions); AdditionalArguments = Other.AdditionalArguments; AdditionalFrameworks.AddRange(Other.AdditionalFrameworks); PrecompiledHeaderFile = Other.PrecompiledHeaderFile; Headers = Other.Headers; bHackHeaderGenerator = Other.bHackHeaderGenerator; bHideSymbolsByDefault = Other.bHideSymbolsByDefault; }
/// <summary> /// Get a set of directly included files from the given source file, resolving their include paths to FileItem instances. /// </summary> /// <param name="SourceFile">The file to check.</param> /// <param name="IncludePaths">Include paths to search.</param> /// <param name="bOnlyCachedDependencies">Whether to just return cached dependencies, or update the cache with new results.</param> /// <returns>Set of files that are included</returns> private HashSet <FileItem> GetDirectlyIncludedFiles(FileItem SourceFile, CppIncludePaths IncludePaths, bool bOnlyCachedDependencies) { // Gather a list of names of files directly included by this C++ file. List <DependencyInclude> DirectIncludes = GetDirectIncludeDependencies(SourceFile, bOnlyCachedDependencies: bOnlyCachedDependencies); // Build a list of the unique set of files that are included by this file. HashSet <FileItem> DirectlyIncludedFiles = new HashSet <FileItem>(); // require a for loop here because we need to keep track of the index in the list. for (int DirectlyIncludedFileNameIndex = 0; DirectlyIncludedFileNameIndex < DirectIncludes.Count; ++DirectlyIncludedFileNameIndex) { // Resolve the included file name to an actual file. DependencyInclude DirectInclude = DirectIncludes[DirectlyIncludedFileNameIndex]; if (!DirectInclude.HasAttemptedResolve || // ignore any preexisting resolve cache if we are not configured to use it. !bUseIncludeDependencyResolveCache || // if we are testing the resolve cache, we force UBT to resolve every time to look for conflicts bTestIncludeDependencyResolveCache ) { ++TotalDirectIncludeResolveCacheMisses; // search the include paths to resolve the file FileItem DirectIncludeResolvedFile = CPPHeaders.FindIncludedFile(SourceFile.Location, DirectInclude.IncludeName, IncludePaths); if (DirectIncludeResolvedFile != null) { DirectlyIncludedFiles.Add(DirectIncludeResolvedFile); } IncludeDependencyCache.CacheResolvedIncludeFullPath(SourceFile, DirectlyIncludedFileNameIndex, DirectIncludeResolvedFile != null ? DirectIncludeResolvedFile.Location : null, bUseIncludeDependencyResolveCache, bTestIncludeDependencyResolveCache); } else { // we might have cached an attempt to resolve the file, but couldn't actually find the file (system headers, etc). if (DirectInclude.IncludeResolvedNameIfSuccessful != null) { DirectlyIncludedFiles.Add(FileItem.GetItemByFileReference(DirectInclude.IncludeResolvedNameIfSuccessful)); } } } TotalDirectIncludeResolves += DirectIncludes.Count; return(DirectlyIncludedFiles); }
/// <summary> /// Finds the files directly or indirectly included by the given C++ file. /// </summary> /// <param name="CPPFile">C++ file to get the dependencies for.</param> /// <param name="Result">List of CPPFile dependencies.</param> /// <returns>false if CPPFile is still being processed further down the callstack, true otherwise.</returns> public bool FindAndCacheAllIncludedFiles(FileItem CPPFile, UEBuildPlatform BuildPlatform, CPPIncludeInfo CPPIncludeInfo, ref IncludedFilesSet Result, bool bOnlyCachedDependencies) { IncludedFilesSet IncludedFileList; Dictionary <FileItem, IncludedFilesSet> IncludedFilesMap = bOnlyCachedDependencies ? OnlyCachedIncludedFilesMap : ExhaustiveIncludedFilesMap; if (!IncludedFilesMap.TryGetValue(CPPFile, out IncludedFileList)) { DateTime TimerStartTime = DateTime.UtcNow; IncludedFileList = new IncludedFilesSet(); // Add an uninitialized entry for the include file to avoid infinitely recursing on include file loops. IncludedFilesMap.Add(CPPFile, IncludedFileList); // Gather a list of names of files directly included by this C++ file. List <DependencyInclude> DirectIncludes = GetDirectIncludeDependencies(CPPFile, BuildPlatform, bOnlyCachedDependencies: bOnlyCachedDependencies); // Build a list of the unique set of files that are included by this file. HashSet <FileItem> DirectlyIncludedFiles = new HashSet <FileItem>(); // require a for loop here because we need to keep track of the index in the list. for (int DirectlyIncludedFileNameIndex = 0; DirectlyIncludedFileNameIndex < DirectIncludes.Count; ++DirectlyIncludedFileNameIndex) { // Resolve the included file name to an actual file. DependencyInclude DirectInclude = DirectIncludes[DirectlyIncludedFileNameIndex]; if (!DirectInclude.HasAttemptedResolve || // 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 ) { ++TotalDirectIncludeResolveCacheMisses; // search the include paths to resolve the file FileItem DirectIncludeResolvedFile = CPPHeaders.FindIncludedFile(DirectInclude.IncludeName, !BuildConfiguration.bCheckExternalHeadersForModification, CPPIncludeInfo.GetIncludesPathsToSearch(CPPFile), CPPIncludeInfo.IncludeFileSearchDictionary); if (DirectIncludeResolvedFile != null) { DirectlyIncludedFiles.Add(DirectIncludeResolvedFile); } IncludeDependencyCache.CacheResolvedIncludeFullPath(CPPFile, DirectlyIncludedFileNameIndex, DirectIncludeResolvedFile != null ? DirectIncludeResolvedFile.Reference : null); } else { // we might have cached an attempt to resolve the file, but couldn't actually find the file (system headers, etc). if (DirectInclude.IncludeResolvedNameIfSuccessful != null) { DirectlyIncludedFiles.Add(FileItem.GetItemByFileReference(DirectInclude.IncludeResolvedNameIfSuccessful)); } } } TotalDirectIncludeResolves += DirectIncludes.Count; // Convert the dictionary of files included by this file into a list. foreach (FileItem DirectlyIncludedFile in DirectlyIncludedFiles) { // Add the file we're directly including IncludedFileList.Add(DirectlyIncludedFile); // Also add all of the indirectly included files! if (FindAndCacheAllIncludedFiles(DirectlyIncludedFile, BuildPlatform, CPPIncludeInfo, ref IncludedFileList, bOnlyCachedDependencies: bOnlyCachedDependencies) == false) { // DirectlyIncludedFile is a circular dependency which is still being processed // further down the callstack. Add this file to its circular dependencies list // so that it can update its dependencies later. IncludedFilesSet DirectlyIncludedFileIncludedFileList; if (IncludedFilesMap.TryGetValue(DirectlyIncludedFile, out DirectlyIncludedFileIncludedFileList)) { DirectlyIncludedFileIncludedFileList.CircularDependencies.Add(CPPFile); } } } // All dependencies have been processed by now so update all circular dependencies // with the full list. foreach (FileItem CircularDependency in IncludedFileList.CircularDependencies) { IncludedFilesSet CircularDependencyIncludedFiles = IncludedFilesMap[CircularDependency]; foreach (FileItem IncludedFile in IncludedFileList) { CircularDependencyIncludedFiles.Add(IncludedFile); } } // No need to keep this around anymore. IncludedFileList.CircularDependencies.Clear(); // Done collecting files. IncludedFileList.bIsInitialized = true; TimeSpan TimerDuration = DateTime.UtcNow - TimerStartTime; TotalTimeSpentGettingIncludes += TimerDuration.TotalSeconds; } if (IncludedFileList.bIsInitialized) { // Copy the list of files included by this file into the result list. foreach (FileItem IncludedFile in IncludedFileList) { // If the result list doesn't contain this file yet, add the file and the files it includes. // NOTE: For some reason in .NET 4, Add() is over twice as fast as calling UnionWith() on the set Result.Add(IncludedFile); } return(true); } else { // The IncludedFileList.bIsInitialized was false because we added a dummy entry further down the call stack. We're already processing // the include list for this header elsewhere in the stack frame, so we don't need to add anything here. return(false); } }
/// <summary> /// Loads a UBTMakefile from disk /// </summary> /// <param name="MakefilePath">Path to the makefile to load</param> /// <param name="ProjectFile">Path to the project file</param> /// <param name="ReasonNotLoaded">If the function returns null, this string will contain the reason why</param> /// <param name="WorkingSet">Interface to query which source files are in the working set</param> /// <returns>The loaded makefile, or null if it failed for some reason. On failure, the 'ReasonNotLoaded' variable will contain information about why</returns> public static UBTMakefile LoadUBTMakefile(FileReference MakefilePath, FileReference ProjectFile, ISourceFileWorkingSet WorkingSet, out string ReasonNotLoaded) { // Check the directory timestamp on the project files directory. If the user has generated project files more // recently than the UBTMakefile, then we need to consider the file to be out of date FileInfo UBTMakefileInfo = new FileInfo(MakefilePath.FullName); if (!UBTMakefileInfo.Exists) { // UBTMakefile doesn't even exist, so we won't bother loading it ReasonNotLoaded = "no existing makefile"; return(null); } // Check the build version FileInfo BuildVersionFileInfo = new FileInfo(BuildVersion.GetDefaultFileName().FullName); if (BuildVersionFileInfo.Exists && UBTMakefileInfo.LastWriteTime.CompareTo(BuildVersionFileInfo.LastWriteTime) < 0) { Log.TraceVerbose("Existing makefile is older than Build.version, ignoring it"); ReasonNotLoaded = "Build.version is newer"; return(null); } // @todo ubtmake: This will only work if the directory timestamp actually changes with every single GPF. Force delete existing files before creating new ones? Eh... really we probably just want to delete + create a file in that folder // -> UPDATE: Seems to work OK right now though on Windows platform, maybe due to GUID changes // @todo ubtmake: Some platforms may not save any files into this folder. We should delete + generate a "touch" file to force the directory timestamp to be updated (or just check the timestamp file itself. We could put it ANYWHERE, actually) // Installed Build doesn't need to check engine projects for outdatedness if (!UnrealBuildTool.IsEngineInstalled()) { if (DirectoryReference.Exists(ProjectFileGenerator.IntermediateProjectFilesPath)) { DateTime EngineProjectFilesLastUpdateTime = new FileInfo(ProjectFileGenerator.ProjectTimestampFile).LastWriteTime; if (UBTMakefileInfo.LastWriteTime.CompareTo(EngineProjectFilesLastUpdateTime) < 0) { // Engine project files are newer than UBTMakefile Log.TraceVerbose("Existing makefile is older than generated engine project files, ignoring it"); ReasonNotLoaded = "project files are newer"; return(null); } } } // Check the game project directory too if (ProjectFile != null) { string ProjectFilename = ProjectFile.FullName; FileInfo ProjectFileInfo = new FileInfo(ProjectFilename); if (!ProjectFileInfo.Exists || UBTMakefileInfo.LastWriteTime.CompareTo(ProjectFileInfo.LastWriteTime) < 0) { // .uproject file is newer than UBTMakefile Log.TraceVerbose("Makefile is older than .uproject file, ignoring it"); ReasonNotLoaded = ".uproject file is newer"; return(null); } DirectoryReference MasterProjectRelativePath = ProjectFile.Directory; string GameIntermediateProjectFilesPath = Path.Combine(MasterProjectRelativePath.FullName, "Intermediate", "ProjectFiles"); if (Directory.Exists(GameIntermediateProjectFilesPath)) { DateTime GameProjectFilesLastUpdateTime = new DirectoryInfo(GameIntermediateProjectFilesPath).LastWriteTime; if (UBTMakefileInfo.LastWriteTime.CompareTo(GameProjectFilesLastUpdateTime) < 0) { // Game project files are newer than UBTMakefile Log.TraceVerbose("Makefile is older than generated game project files, ignoring it"); ReasonNotLoaded = "game project files are newer"; return(null); } } } // Check to see if UnrealBuildTool.exe was compiled more recently than the UBTMakefile DateTime UnrealBuildToolTimestamp = new FileInfo(Assembly.GetExecutingAssembly().Location).LastWriteTime; if (UBTMakefileInfo.LastWriteTime.CompareTo(UnrealBuildToolTimestamp) < 0) { // UnrealBuildTool.exe was compiled more recently than the UBTMakefile Log.TraceVerbose("Makefile is older than UnrealBuildTool.exe, ignoring it"); ReasonNotLoaded = "UnrealBuildTool.exe is newer"; return(null); } // Check to see if any BuildConfiguration files have changed since the last build List <XmlConfig.InputFile> InputFiles = XmlConfig.FindInputFiles(); foreach (XmlConfig.InputFile InputFile in InputFiles) { FileInfo InputFileInfo = new FileInfo(InputFile.Location.FullName); if (InputFileInfo.LastWriteTime > UBTMakefileInfo.LastWriteTime) { Log.TraceVerbose("Makefile is older than BuildConfiguration.xml, ignoring it"); ReasonNotLoaded = "BuildConfiguration.xml is newer"; return(null); } } UBTMakefile LoadedUBTMakefile = null; try { DateTime LoadUBTMakefileStartTime = DateTime.UtcNow; using (FileStream Stream = new FileStream(UBTMakefileInfo.FullName, FileMode.Open, FileAccess.Read)) { BinaryFormatter Formatter = new BinaryFormatter(); LoadedUBTMakefile = Formatter.Deserialize(Stream) as UBTMakefile; } if (UnrealBuildTool.bPrintPerformanceInfo) { double LoadUBTMakefileTime = (DateTime.UtcNow - LoadUBTMakefileStartTime).TotalSeconds; Log.TraceInformation("LoadUBTMakefile took " + LoadUBTMakefileTime + "s"); } } catch (Exception Ex) { Log.TraceWarning("Failed to read makefile: {0}", Ex.Message); ReasonNotLoaded = "couldn't read existing makefile"; return(null); } if (!LoadedUBTMakefile.IsValidMakefile()) { Log.TraceWarning("Loaded makefile appears to have invalid contents, ignoring it ({0})", UBTMakefileInfo.FullName); ReasonNotLoaded = "existing makefile appears to be invalid"; return(null); } // Check if any of the target's Build.cs files are newer than the makefile foreach (UEBuildTarget Target in LoadedUBTMakefile.Targets) { string TargetCsFilename = Target.TargetRulesFile.FullName; if (TargetCsFilename != null) { FileInfo TargetCsFile = new FileInfo(TargetCsFilename); bool bTargetCsFileExists = TargetCsFile.Exists; if (!bTargetCsFileExists || TargetCsFile.LastWriteTime > UBTMakefileInfo.LastWriteTime) { Log.TraceVerbose("{0} has been {1} since makefile was built, ignoring it ({2})", TargetCsFilename, bTargetCsFileExists ? "changed" : "deleted", UBTMakefileInfo.FullName); ReasonNotLoaded = string.Format("changes to target files"); return(null); } } IEnumerable <string> BuildCsFilenames = Target.GetAllModuleBuildCsFilenames(); foreach (string BuildCsFilename in BuildCsFilenames) { if (BuildCsFilename != null) { FileInfo BuildCsFile = new FileInfo(BuildCsFilename); bool bBuildCsFileExists = BuildCsFile.Exists; if (!bBuildCsFileExists || BuildCsFile.LastWriteTime > UBTMakefileInfo.LastWriteTime) { Log.TraceVerbose("{0} has been {1} since makefile was built, ignoring it ({2})", BuildCsFilename, bBuildCsFileExists ? "changed" : "deleted", UBTMakefileInfo.FullName); ReasonNotLoaded = string.Format("changes to module files"); return(null); } } } foreach (FlatModuleCsDataType FlatCsModuleData in Target.FlatModuleCsData.Values) { if (FlatCsModuleData.BuildCsFilename != null && FlatCsModuleData.ExternalDependencies.Count > 0) { string BaseDir = Path.GetDirectoryName(FlatCsModuleData.BuildCsFilename); foreach (string ExternalDependency in FlatCsModuleData.ExternalDependencies) { FileInfo DependencyFile = new FileInfo(Path.Combine(BaseDir, ExternalDependency)); bool bDependencyFileExists = DependencyFile.Exists; if (!bDependencyFileExists || DependencyFile.LastWriteTime > UBTMakefileInfo.LastWriteTime) { Log.TraceVerbose("{0} has been {1} since makefile was built, ignoring it ({2})", DependencyFile.FullName, bDependencyFileExists ? "changed" : "deleted", UBTMakefileInfo.FullName); ReasonNotLoaded = string.Format("changes to external dependency"); return(null); } } } } } // We do a check to see if any modules' headers have changed which have // acquired or lost UHT types. If so, which should be rare, // we'll just invalidate the entire makefile and force it to be rebuilt. foreach (UEBuildTarget Target in LoadedUBTMakefile.Targets) { // Get all H files in processed modules newer than the makefile itself HashSet <string> HFilesNewerThanMakefile = new HashSet <string>( Target.FlatModuleCsData .SelectMany(x => x.Value.ModuleSourceFolder != null ? Directory.EnumerateFiles(x.Value.ModuleSourceFolder.FullName, "*.h", SearchOption.AllDirectories) : Enumerable.Empty <string>()) .Where(y => Directory.GetLastWriteTimeUtc(y) > UBTMakefileInfo.LastWriteTimeUtc) .OrderBy(z => z).Distinct() ); // Get all H files in all modules processed in the last makefile build HashSet <string> AllUHTHeaders = new HashSet <string>(Target.FlatModuleCsData.Select(x => x.Value).SelectMany(x => x.UHTHeaderNames)); // Check whether any headers have been deleted. If they have, we need to regenerate the makefile since the module might now be empty. If we don't, // and the file has been moved to a different module, we may include stale generated headers. foreach (string FileName in AllUHTHeaders) { if (!File.Exists(FileName)) { Log.TraceVerbose("File processed by UHT was deleted ({0}); invalidating makefile", FileName); ReasonNotLoaded = string.Format("UHT file was deleted"); return(null); } } // Makefile is invalid if: // * There are any newer files which contain no UHT data, but were previously in the makefile // * There are any newer files contain data which needs processing by UHT, but weren't not previously in the makefile foreach (string Filename in HFilesNewerThanMakefile) { bool bContainsUHTData = CPPHeaders.DoesFileContainUObjects(Filename); bool bWasProcessed = AllUHTHeaders.Contains(Filename); if (bContainsUHTData != bWasProcessed) { Log.TraceVerbose("{0} {1} contain UHT types and now {2} , ignoring it ({3})", Filename, bWasProcessed ? "used to" : "didn't", bWasProcessed ? "doesn't" : "does", UBTMakefileInfo.FullName); ReasonNotLoaded = string.Format("new files with reflected types"); return(null); } } } // If adaptive unity build is enabled, do a check to see if there are any source files that became part of the // working set since the Makefile was created (or, source files were removed from the working set.) If anything // changed, then we'll force a new Makefile to be created so that we have fresh unity build blobs. We always // want to make sure that source files in the working set are excluded from those unity blobs (for fastest possible // iteration times.) if (LoadedUBTMakefile.bUseAdaptiveUnityBuild) { // Check if any source files in the working set no longer belong in it foreach (FileItem SourceFile in LoadedUBTMakefile.SourceFileWorkingSet) { if (!WorkingSet.Contains(SourceFile.Location) && File.GetLastWriteTimeUtc(SourceFile.AbsolutePath) > UBTMakefileInfo.LastWriteTimeUtc) { Log.TraceVerbose("{0} was part of source working set and now is not; invalidating makefile ({1})", SourceFile.AbsolutePath, UBTMakefileInfo.FullName); ReasonNotLoaded = string.Format("working set of source files changed"); return(null); } } // Check if any source files that are eligible for being in the working set have been modified foreach (FileItem SourceFile in LoadedUBTMakefile.CandidateSourceFilesForWorkingSet) { if (WorkingSet.Contains(SourceFile.Location) && File.GetLastWriteTimeUtc(SourceFile.AbsolutePath) > UBTMakefileInfo.LastWriteTimeUtc) { Log.TraceVerbose("{0} was part of source working set and now is not; invalidating makefile ({1})", SourceFile.AbsolutePath, UBTMakefileInfo.FullName); ReasonNotLoaded = string.Format("working set of source files changed"); return(null); } } } ReasonNotLoaded = null; return(LoadedUBTMakefile); }
/// <summary> /// Default constructor. /// </summary> public CPPEnvironment(CPPHeaders Headers) { this.Headers = Headers; }