Пример #1
0
        /// <summary>
        /// Finds all the source files under a directory that contain reflection markup
        /// </summary>
        /// <param name="Directory">The directory to search</param>
        /// <param name="MetadataCache">Cache of source file metadata</param>
        /// <param name="ExcludedFolderNames">Set of folder names to ignore when recursing the directory tree</param>
        /// <param name="FilesWithMarkup">Receives the set of files which contain reflection markup</param>
        /// <param name="Queue">Queue to add sub-tasks to</param>
        static void FindFilesWithMarkup(DirectoryItem Directory, SourceFileMetadataCache MetadataCache, ReadOnlyHashSet <string> ExcludedFolderNames, ConcurrentBag <FileItem> FilesWithMarkup, ThreadPoolWorkQueue Queue)
        {
            // Search through all the subfolders
            foreach (DirectoryItem SubDirectory in Directory.EnumerateDirectories())
            {
                if (!ExcludedFolderNames.Contains(SubDirectory.Name))
                {
                    Queue.Enqueue(() => FindFilesWithMarkup(SubDirectory, MetadataCache, ExcludedFolderNames, FilesWithMarkup, Queue));
                }
            }

            // Check for all the headers in this folder
            foreach (FileItem File in Directory.EnumerateFiles())
            {
                if (File.HasExtension(".h") && MetadataCache.ContainsReflectionMarkup(File))
                {
                    FilesWithMarkup.Add(File);
                }
            }
        }
 /// <summary>
 /// Determines whether the given file contains reflection markup
 /// </summary>
 /// <param name="SourceFile">The source file to parse</param>
 /// <returns>True if the file contains reflection markup</returns>
 public bool ContainsReflectionMarkup(FileItem SourceFile)
 {
     if (Parent != null && !SourceFile.Location.IsUnderDirectory(BaseDirectory))
     {
         return(Parent.ContainsReflectionMarkup(SourceFile));
     }
     else
     {
         ReflectionInfo ReflectionInfo;
         if (!FileToReflectionInfo.TryGetValue(SourceFile, out ReflectionInfo) || SourceFile.LastWriteTimeUtc.Ticks > ReflectionInfo.LastWriteTimeUtc)
         {
             ReflectionInfo = new ReflectionInfo();
             ReflectionInfo.LastWriteTimeUtc  = SourceFile.LastWriteTimeUtc.Ticks;
             ReflectionInfo.bContainsMarkup   = ReflectionMarkupRegex.IsMatch(FileReference.ReadAllText(SourceFile.Location));
             FileToReflectionInfo[SourceFile] = ReflectionInfo;
             bModified = true;
         }
         return(ReflectionInfo.bContainsMarkup);
     }
 }
Пример #3
0
        /// <summary>
        /// Checks if the makefile is valid for the current set of source files. This is done separately to the Load() method to allow pre-build steps to modify source files.
        /// </summary>
        /// <param name="Makefile">The makefile that has been loaded</param>
        /// <param name="ProjectFile">Path to the project file</param>
        /// <param name="WorkingSet">The current working set of source files</param>
        /// <param name="ReasonNotLoaded">If the makefile is not valid, is set to a message describing why</param>
        /// <returns>True if the makefile is valid, false otherwise</returns>
        public static bool IsValidForSourceFiles(TargetMakefile Makefile, FileReference ProjectFile, ISourceFileWorkingSet WorkingSet, out string ReasonNotLoaded)
        {
            using (Timeline.ScopeEvent("TargetMakefile.IsValidForSourceFiles()"))
            {
                // Check if any source files have been added or removed
                foreach (KeyValuePair <DirectoryItem, FileItem[]> Pair in Makefile.DirectoryToSourceFiles)
                {
                    DirectoryItem InputDirectory = Pair.Key;
                    if (!InputDirectory.Exists || InputDirectory.LastWriteTimeUtc > Makefile.CreateTimeUtc)
                    {
                        FileItem[] SourceFiles = UEBuildModuleCPP.GetSourceFiles(InputDirectory);
                        if (SourceFiles.Length < Pair.Value.Length)
                        {
                            ReasonNotLoaded = "source file removed";
                            return(false);
                        }
                        else if (SourceFiles.Length > Pair.Value.Length)
                        {
                            ReasonNotLoaded = "source file added";
                            return(false);
                        }
                        else if (SourceFiles.Intersect(Pair.Value).Count() != SourceFiles.Length)
                        {
                            ReasonNotLoaded = "source file modified";
                            return(false);
                        }
                    }
                }

                // Check if any of the additional dependencies has changed
                foreach (FileItem AdditionalDependency in Makefile.AdditionalDependencies)
                {
                    if (!AdditionalDependency.Exists)
                    {
                        Log.TraceLog("{0} has been deleted since makefile was built.", AdditionalDependency.Location);
                        ReasonNotLoaded = string.Format("{0} deleted", AdditionalDependency.Location.GetFileName());
                        return(false);
                    }
                    if (AdditionalDependency.LastWriteTimeUtc > Makefile.CreateTimeUtc)
                    {
                        Log.TraceLog("{0} has been modified since makefile was built.", AdditionalDependency.Location);
                        ReasonNotLoaded = string.Format("{0} modified", AdditionalDependency.Location.GetFileName());
                        return(false);
                    }
                }

                // Check that no new plugins have been added
                foreach (FileReference PluginFile in Plugins.EnumeratePlugins(ProjectFile))
                {
                    FileItem PluginFileItem = FileItem.GetItemByFileReference(PluginFile);
                    if (!Makefile.PluginFiles.Contains(PluginFileItem))
                    {
                        Log.TraceLog("{0} has been added", PluginFile.GetFileName());
                        ReasonNotLoaded = string.Format("{0} has been added", PluginFile.GetFileName());
                        return(false);
                    }
                }

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

                // Get all H files in processed modules newer than the makefile itself
                HashSet <FileItem> HFilesNewerThanMakefile = new HashSet <FileItem>();
                foreach (UHTModuleHeaderInfo ModuleHeaderInfo in Makefile.UObjectModuleHeaders)
                {
                    foreach (FileItem HeaderFile in ModuleHeaderInfo.SourceFolder.EnumerateFiles())
                    {
                        if (HeaderFile.HasExtension(".h") && HeaderFile.LastWriteTimeUtc > Makefile.CreateTimeUtc)
                        {
                            HFilesNewerThanMakefile.Add(HeaderFile);
                        }
                    }
                }

                // Get all H files in all modules processed in the last makefile build
                HashSet <FileItem> AllUHTHeaders = new HashSet <FileItem>(Makefile.UObjectModuleHeaders.SelectMany(x => x.HeaderFiles));

                // 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 (FileItem HeaderFile in AllUHTHeaders)
                {
                    if (!HeaderFile.Exists)
                    {
                        Log.TraceLog("File processed by UHT was deleted ({0}); invalidating makefile", HeaderFile);
                        ReasonNotLoaded = string.Format("UHT file was deleted");
                        return(false);
                    }
                }

                // 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
                SourceFileMetadataCache MetadataCache = SourceFileMetadataCache.CreateHierarchy(ProjectFile);
                foreach (FileItem HeaderFile in HFilesNewerThanMakefile)
                {
                    bool bContainsUHTData = MetadataCache.ContainsReflectionMarkup(HeaderFile);
                    bool bWasProcessed    = AllUHTHeaders.Contains(HeaderFile);
                    if (bContainsUHTData != bWasProcessed)
                    {
                        Log.TraceLog("{0} {1} contain UHT types and now {2} , ignoring it", HeaderFile, bWasProcessed ? "used to" : "didn't", bWasProcessed ? "doesn't" : "does");
                        ReasonNotLoaded = string.Format("new files with reflected types");
                        return(false);
                    }
                }

                // 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.)

                // Check if any source files in the working set no longer belong in it
                foreach (FileItem SourceFile in Makefile.WorkingSet)
                {
                    if (!WorkingSet.Contains(SourceFile) && SourceFile.LastWriteTimeUtc > Makefile.CreateTimeUtc)
                    {
                        Log.TraceLog("{0} was part of source working set and now is not; invalidating makefile", SourceFile.AbsolutePath);
                        ReasonNotLoaded = string.Format("working set of source files changed");
                        return(false);
                    }
                }

                // Check if any source files that are eligible for being in the working set have been modified
                foreach (FileItem SourceFile in Makefile.CandidatesForWorkingSet)
                {
                    if (WorkingSet.Contains(SourceFile) && SourceFile.LastWriteTimeUtc > Makefile.CreateTimeUtc)
                    {
                        Log.TraceLog("{0} was part of source working set and now is not", SourceFile.AbsolutePath);
                        ReasonNotLoaded = string.Format("working set of source files changed");
                        return(false);
                    }
                }
            }

            ReasonNotLoaded = null;
            return(true);
        }