/// <summary> /// Prefetch multiple directories in parallel /// </summary> /// <param name="Directories">The directories to cache</param> private static void PrefetchRulesFiles(IEnumerable <DirectoryReference> Directories) { ThreadPoolWorkQueue Queue = null; try { foreach (DirectoryReference Directory in Directories) { if (!RootFolderToRulesFileCache.ContainsKey(Directory)) { RulesFileCache Cache = new RulesFileCache(); RootFolderToRulesFileCache[Directory] = Cache; if (Queue == null) { Queue = new ThreadPoolWorkQueue(); } DirectoryItem DirectoryItem = DirectoryItem.GetItemByDirectoryReference(Directory); Queue.Enqueue(() => FindAllRulesFilesRecursively(DirectoryItem, Cache, Queue)); } } } finally { if (Queue != null) { Queue.Dispose(); Queue = null; } } }
private static IReadOnlyList <FileReference> FindAllRulesFiles(DirectoryReference Directory, RulesFileType Type) { // Check to see if we've already cached source files for this folder RulesFileCache Cache; if (!RootFolderToRulesFileCache.TryGetValue(Directory, out Cache)) { Cache = new RulesFileCache(); FindAllRulesFilesRecursively(Directory, Cache); RootFolderToRulesFileCache[Directory] = Cache; } // Get the list of files of the type we're looking for if (Type == RulesCompiler.RulesFileType.Module) { return(Cache.ModuleRules); } else if (Type == RulesCompiler.RulesFileType.Target) { return(Cache.TargetRules); } else if (Type == RulesCompiler.RulesFileType.AutomationModule) { return(Cache.AutomationModules); } else { throw new BuildException("Unhandled rules type: {0}", Type); } }
private static void FindAllRulesFilesRecursively(DirectoryReference Directory, RulesFileCache Cache) { // Scan all the files in this directory bool bSearchSubFolders = true; foreach (FileReference File in DirectoryLookupCache.EnumerateFiles(Directory)) { if (File.HasExtension(".build.cs")) { Cache.ModuleRules.Add(File); bSearchSubFolders = false; } else if (File.HasExtension(".target.cs")) { Cache.TargetRules.Add(File); } else if (File.HasExtension(".automation.csproj")) { Cache.AutomationModules.Add(File); bSearchSubFolders = false; } } // If we didn't find anything to stop the search, search all the subdirectories too if (bSearchSubFolders) { foreach (DirectoryReference SubDirectory in DirectoryLookupCache.EnumerateDirectories(Directory)) { FindAllRulesFilesRecursively(SubDirectory, Cache); } } }
/// <summary> /// Search through a directory tree for any rules files /// </summary> /// <param name="Directory">The root directory to search from</param> /// <param name="Cache">Receives all the discovered rules files</param> /// <param name="Queue">Queue for adding additional tasks to</param> private static void FindAllRulesFilesRecursively(DirectoryItem Directory, RulesFileCache Cache, ThreadPoolWorkQueue Queue) { // Scan all the files in this directory bool bSearchSubFolders = true; foreach (FileItem File in Directory.EnumerateFiles()) { if (File.HasExtension(".build.cs")) { lock (Cache.ModuleRules) { Cache.ModuleRules.Add(File.Location); } bSearchSubFolders = false; } else if (File.HasExtension(".target.cs")) { lock (Cache.TargetRules) { Cache.TargetRules.Add(File.Location); } } else if (File.HasExtension(".automation.csproj")) { lock (Cache.AutomationModules) { Cache.AutomationModules.Add(File.Location); } bSearchSubFolders = false; } } // If we didn't find anything to stop the search, search all the subdirectories too if (bSearchSubFolders) { foreach (DirectoryItem SubDirectory in Directory.EnumerateDirectories()) { Queue.Enqueue(() => FindAllRulesFilesRecursively(SubDirectory, Cache, Queue)); } } }
/// <summary> /// Finds all the rules of the given type under a given directory /// </summary> /// <param name="Directory">Directory to search</param> /// <param name="Type">Type of rules to return</param> /// <returns>List of rules files of the given type</returns> private static IReadOnlyList <FileReference> FindAllRulesFiles(DirectoryReference Directory, RulesFileType Type) { // Check to see if we've already cached source files for this folder RulesFileCache Cache; if (!RootFolderToRulesFileCache.TryGetValue(Directory, out Cache)) { Cache = new RulesFileCache(); using (ThreadPoolWorkQueue Queue = new ThreadPoolWorkQueue()) { DirectoryItem BaseDirectory = DirectoryItem.GetItemByDirectoryReference(Directory); Queue.Enqueue(() => FindAllRulesFilesRecursively(BaseDirectory, Cache, Queue)); } Cache.ModuleRules.Sort((A, B) => A.FullName.CompareTo(B.FullName)); Cache.TargetRules.Sort((A, B) => A.FullName.CompareTo(B.FullName)); Cache.AutomationModules.Sort((A, B) => A.FullName.CompareTo(B.FullName)); RootFolderToRulesFileCache[Directory] = Cache; } // Get the list of files of the type we're looking for if (Type == RulesCompiler.RulesFileType.Module) { return(Cache.ModuleRules); } else if (Type == RulesCompiler.RulesFileType.Target) { return(Cache.TargetRules); } else if (Type == RulesCompiler.RulesFileType.AutomationModule) { return(Cache.AutomationModules); } else { throw new BuildException("Unhandled rules type: {0}", Type); } }
public static List<string> FindAllRulesSourceFiles( RulesFileType RulesFileType, List<string> AdditionalSearchPaths ) { List<string> Folders = new List<string>(); // Add all engine source (including third party source) Folders.Add( Path.Combine( ProjectFileGenerator.EngineRelativePath, "Source" ) ); // @todo plugin: Disallow modules from including plugin modules as dependency modules? (except when the module is part of that plugin) // Get all the root folders for plugins List<string> RootFolders = new List<string>(); RootFolders.Add(ProjectFileGenerator.EngineRelativePath); RootFolders.AddRange(AllGameFolders); // Find all the plugin source directories foreach(string RootFolder in RootFolders) { string PluginsFolder = Path.Combine(RootFolder, "Plugins"); foreach(string PluginFile in Plugins.EnumeratePlugins(PluginsFolder)) { string PluginDirectory = Path.GetDirectoryName(PluginFile); Folders.Add(Path.Combine(PluginDirectory, "Source")); } } // Add all the extra plugin folders if( ForeignPlugins != null ) { foreach(string ForeignPlugin in ForeignPlugins) { string PluginDirectory = Path.GetDirectoryName(Path.GetFullPath(ForeignPlugin)); Folders.Add(Path.Combine(PluginDirectory, "Source")); } } // Add in the game folders to search if( AllGameFolders != null ) { foreach( var GameFolder in AllGameFolders ) { var GameSourceFolder = Path.GetFullPath(Path.Combine( GameFolder, "Source" )); Folders.Add( GameSourceFolder ); var GameIntermediateSourceFolder = Path.GetFullPath(Path.Combine(GameFolder, "Intermediate", "Source")); Folders.Add(GameIntermediateSourceFolder); } } // Process the additional search path, if sent in if( AdditionalSearchPaths != null ) { foreach( var AdditionalSearchPath in AdditionalSearchPaths ) { if (!string.IsNullOrEmpty(AdditionalSearchPath)) { if (Directory.Exists(AdditionalSearchPath)) { Folders.Add(AdditionalSearchPath); } else { throw new BuildException( "Couldn't find AdditionalSearchPath for rules source files '{0}'", AdditionalSearchPath ); } } } } var SourceFiles = new List<string>(); // Iterate over all the folders to check foreach( string Folder in Folders ) { // Check to see if we've already cached source files for this folder RulesFileCache FolderRulesFileCache; if (!RootFolderToRulesFileCache.TryGetValue(Folder, out FolderRulesFileCache)) { FolderRulesFileCache = new RulesFileCache(); FindAllRulesFilesRecursively(new DirectoryInfo(Folder), FolderRulesFileCache); RootFolderToRulesFileCache[Folder] = FolderRulesFileCache; if (BuildConfiguration.bPrintDebugInfo) { foreach (var CurType in Enum.GetValues(typeof(RulesFileType))) { var RulesFiles = FolderRulesFileCache.RulesFilePaths[(int)CurType]; if (RulesFiles != null) { Log.TraceVerbose("Found {0} rules files for folder {1} of type {2}", RulesFiles.Count, Folder, CurType.ToString()); } } } } var RulesFilePathsForType = FolderRulesFileCache.RulesFilePaths[(int)RulesFileType]; if (RulesFilePathsForType != null) { foreach (string RulesFilePath in RulesFilePathsForType) { if (!SourceFiles.Contains(RulesFilePath)) { SourceFiles.Add(RulesFilePath); } } } } return SourceFiles; }
private static void FindAllRulesFilesRecursively( DirectoryInfo DirInfo, RulesFileCache RulesFileCache ) { if( DirInfo.Exists ) { var RulesFileTypeEnum = typeof(RulesFileType); bool bFoundModuleRulesFile = false; var RulesFileTypes = typeof( RulesFileType ).GetEnumValues(); foreach( RulesFileType CurRulesType in RulesFileTypes ) { // Get the suffix and extension associated with this RulesFileType enum value. var MemberInfo = RulesFileTypeEnum.GetMember(CurRulesType.ToString()); var Attributes = MemberInfo[0].GetCustomAttributes(typeof(RulesTypePropertiesAttribute), false); var EnumProperties = (RulesTypePropertiesAttribute)Attributes[0]; var SearchRuleSuffix = "." + EnumProperties.Suffix + EnumProperties.Extension; // match files with the right suffix and extension. var FilesInDirectory = DirInfo.GetFiles("*" + EnumProperties.Extension); foreach (var RuleFile in FilesInDirectory) { // test if filename has the appropriate suffix. // this handles filenames such as Foo.build.cs, Foo.Build.cs, foo.bUiLd.cs to fix bug 266743 on platforms where case-sensitivity matters if (RuleFile.Name.EndsWith(SearchRuleSuffix, StringComparison.InvariantCultureIgnoreCase)) { // Skip Uncooked targets, as those are no longer valid. This is just for easier backwards compatibility with existing projects. // @todo: Eventually we can eliminate this conditional and just allow it to be an error when these are compiled if( CurRulesType != RulesFileType.Target || !RuleFile.Name.EndsWith( "Uncooked" + SearchRuleSuffix, StringComparison.InvariantCultureIgnoreCase ) ) { if (RulesFileCache.RulesFilePaths[(int)CurRulesType] == null) { RulesFileCache.RulesFilePaths[(int)CurRulesType] = new List<string>(); } // Convert file info to the full file path for this file and update our cache RulesFileCache.RulesFilePaths[(int)CurRulesType].Add(RuleFile.FullName); // NOTE: Multiple rules files in the same folder are supported. We'll continue iterating along. if( CurRulesType == RulesFileType.Module ) { bFoundModuleRulesFile = true; } } else { Log.TraceVerbose("Skipped deprecated Target rules file with Uncooked extension: " + RuleFile.Name ); } } } } // Only recurse if we didn't find a module rules file. In the interest of performance and organizational sensibility // we don't want to support folders with Build.cs files containing other folders with Build.cs files. Performance- // wise, this is really important to avoid scanning every folder in the Source/ThirdParty directory, for example. if( !bFoundModuleRulesFile ) { // Add all the files recursively foreach( DirectoryInfo SubDirInfo in DirInfo.GetDirectories() ) { if( SubDirInfo.Name.Equals( "Intermediate", StringComparison.InvariantCultureIgnoreCase ) ) { Console.WriteLine( "WARNING: UnrealBuildTool found an Intermediate folder while looking for rules '{0}'. It should only ever be searching under 'Source' folders -- an Intermediate folder is unexpected and will greatly decrease iteration times!", SubDirInfo.FullName ); } FindAllRulesFilesRecursively(SubDirInfo, RulesFileCache); } } } }
private static void FindAllRulesFilesRecursively(DirectoryReference Directory, RulesFileCache Cache) { // Scan all the files in this directory bool bSearchSubFolders = true; foreach (FileReference File in DirectoryLookupCache.EnumerateFiles(Directory)) { if (File.HasExtension(".build.cs")) { Cache.ModuleRules.Add(File); bSearchSubFolders = false; } else if (File.HasExtension(".target.cs")) { Cache.TargetRules.Add(File); } else if (File.HasExtension(".automation.csproj")) { Cache.AutomationModules.Add(File); bSearchSubFolders = false; } } // If we didn't find anything to stop the search, search all the subdirectories too if (bSearchSubFolders) { foreach (DirectoryReference SubDirectory in DirectoryLookupCache.EnumerateDirectories(Directory)) { FindAllRulesFilesRecursively(SubDirectory, Cache); } } }
private static IReadOnlyList<FileReference> FindAllRulesFiles(DirectoryReference Directory, RulesFileType Type) { // Check to see if we've already cached source files for this folder RulesFileCache Cache; if (!RootFolderToRulesFileCache.TryGetValue(Directory, out Cache)) { Cache = new RulesFileCache(); FindAllRulesFilesRecursively(Directory, Cache); RootFolderToRulesFileCache[Directory] = Cache; } // Get the list of files of the type we're looking for if (Type == RulesCompiler.RulesFileType.Module) { return Cache.ModuleRules; } else if (Type == RulesCompiler.RulesFileType.Target) { return Cache.TargetRules; } else if (Type == RulesCompiler.RulesFileType.AutomationModule) { return Cache.AutomationModules; } else { throw new BuildException("Unhandled rules type: {0}", Type); } }