/// <summary> /// Gets all the runtime dependencies Copies all the runtime dependencies from any modules in /// </summary> /// <param name="RuntimeDependencies">The output list of runtime dependencies, mapping target file to type</param> /// <param name="TargetFileToSourceFile">Map of target files to source files that need to be copied</param> /// <param name="ExeDir">Output directory for the executable</param> public void PrepareRuntimeDependencies(List <RuntimeDependency> RuntimeDependencies, Dictionary <FileReference, FileReference> TargetFileToSourceFile, DirectoryReference ExeDir) { foreach (UEBuildModule Module in Modules) { foreach (ModuleRules.RuntimeDependency Dependency in Module.Rules.RuntimeDependencies.Inner) { if (Dependency.SourcePath == null) { // Expand the target path string ExpandedPath = Module.ExpandPathVariables(Dependency.Path, OutputDir, ExeDir); if (FileFilter.FindWildcardIndex(ExpandedPath) == -1) { RuntimeDependencies.Add(new RuntimeDependency(new FileReference(ExpandedPath), Dependency.Type)); } else { RuntimeDependencies.AddRange(FileFilter.ResolveWildcard(ExpandedPath).Select(x => new RuntimeDependency(x, Dependency.Type))); } } else { // Parse the source and target patterns FilePattern SourcePattern = new FilePattern(UnrealBuildTool.EngineSourceDirectory, Module.ExpandPathVariables(Dependency.SourcePath, OutputDir, ExeDir)); FilePattern TargetPattern = new FilePattern(UnrealBuildTool.EngineSourceDirectory, Module.ExpandPathVariables(Dependency.Path, OutputDir, ExeDir)); // Resolve all the wildcards between the source and target paths Dictionary <FileReference, FileReference> Mapping; try { Mapping = FilePattern.CreateMapping(null, ref SourcePattern, ref TargetPattern); } catch (FilePatternException Ex) { ExceptionUtils.AddContext(Ex, "while creating runtime dependencies for module '{0}'", Module.Name); throw; } // Add actions to copy everything foreach (KeyValuePair <FileReference, FileReference> Pair in Mapping) { FileReference ExistingSourceFile; if (!TargetFileToSourceFile.TryGetValue(Pair.Key, out ExistingSourceFile)) { TargetFileToSourceFile[Pair.Key] = Pair.Value; RuntimeDependencies.Add(new RuntimeDependency(Pair.Key, Dependency.Type)); } else if (ExistingSourceFile != Pair.Value) { throw new BuildException("Runtime dependency '{0}' is configured to be staged from '{1}' and '{2}'", Pair.Key, Pair.Value, ExistingSourceFile); } } } } } }
/// <summary> /// Gets all the runtime dependencies Copies all the runtime dependencies from any modules in /// </summary> /// <param name="RuntimeDependencies">The output list of runtime dependencies, mapping target file to type</param> /// <param name="SourceFiles">Receives the list of source files that were copied</param> /// <param name="ActionGraph">Actions to be executed</param> public IEnumerable <FileItem> PrepareRuntimeDependencies(List <RuntimeDependency> RuntimeDependencies, List <FileReference> SourceFiles, ActionGraph ActionGraph) { List <FileItem> CopiedFiles = new List <FileItem>(); foreach (UEBuildModule Module in Modules) { foreach (ModuleRules.RuntimeDependency Dependency in Module.Rules.RuntimeDependencies.Inner) { if (Dependency.SourcePath == null) { // Expand the target path string ExpandedPath = Module.ExpandPathVariables(Dependency.Path, this); if (FileFilter.FindWildcardIndex(ExpandedPath) == -1) { RuntimeDependencies.Add(new RuntimeDependency(new FileReference(ExpandedPath), Dependency.Type)); } else { RuntimeDependencies.AddRange(FileFilter.ResolveWildcard(ExpandedPath).Select(x => new RuntimeDependency(x, Dependency.Type))); } } else { // Parse the source and target patterns FilePattern SourcePattern = new FilePattern(UnrealBuildTool.EngineSourceDirectory, Module.ExpandPathVariables(Dependency.SourcePath, this)); FilePattern TargetPattern = new FilePattern(UnrealBuildTool.EngineSourceDirectory, Module.ExpandPathVariables(Dependency.Path, this)); // Resolve all the wildcards between the source and target paths Dictionary <FileReference, FileReference> Mapping; try { Mapping = FilePattern.CreateMapping(null, ref SourcePattern, ref TargetPattern); } catch (FilePatternException Ex) { throw new BuildException(Ex, "While creating runtime dependencies for module {0}", Module.Name); } // Add actions to copy everything foreach (KeyValuePair <FileReference, FileReference> Pair in Mapping) { CopiedFiles.Add(CreateCopyAction(Pair.Value, Pair.Key, ActionGraph)); SourceFiles.Add(Pair.Value); RuntimeDependencies.Add(new RuntimeDependency(Pair.Key, Dependency.Type)); } } } } return(CopiedFiles); }
/// <summary> /// Execute the task. /// </summary> /// <param name="Job">Information about the current job</param> /// <param name="BuildProducts">Set of build products produced by this node.</param> /// <param name="TagNameToFileSet">Mapping from tag names to the set of files they include</param> public override void Execute(JobContext Job, HashSet <FileReference> BuildProducts, Dictionary <string, HashSet <FileReference> > TagNameToFileSet) { // Parse all the source patterns FilePattern SourcePattern = new FilePattern(CommandUtils.RootDirectory, Parameters.From); // Parse the target pattern FilePattern TargetPattern = new FilePattern(CommandUtils.RootDirectory, Parameters.To); // Apply the filter to the source files HashSet <FileReference> Files = null; if (!String.IsNullOrEmpty(Parameters.Files)) { SourcePattern = SourcePattern.AsDirectoryPattern(); Files = ResolveFilespec(SourcePattern.BaseDirectory, Parameters.Files, TagNameToFileSet); } // Build the file mapping Dictionary <FileReference, FileReference> TargetFileToSourceFile = FilePattern.CreateMapping(Files, SourcePattern, TargetPattern); // Check we got some files if (TargetFileToSourceFile.Count == 0) { CommandUtils.Log("No files found matching '{0}'", SourcePattern); return; } // Copy them all KeyValuePair <FileReference, FileReference>[] FilePairs = TargetFileToSourceFile.ToArray(); CommandUtils.Log("Copying {0} file{1} from {2} to {3}...", FilePairs.Length, (FilePairs.Length == 1)? "" : "s", SourcePattern.BaseDirectory, TargetPattern.BaseDirectory); CommandUtils.ThreadedCopyFiles(FilePairs.Select(x => x.Value.FullName).ToList(), FilePairs.Select(x => x.Key.FullName).ToList(), bQuiet: true); // Update the list of build products BuildProducts.UnionWith(TargetFileToSourceFile.Keys); // Apply the optional output tag to them foreach (string TagName in FindTagNamesFromList(Parameters.Tag)) { FindOrAddTagSet(TagNameToFileSet, TagName).UnionWith(TargetFileToSourceFile.Keys); } }
/// <summary> /// Execute the task. /// </summary> /// <param name="Job">Information about the current job</param> /// <param name="BuildProducts">Set of build products produced by this node.</param> /// <param name="TagNameToFileSet">Mapping from tag names to the set of files they include</param> public override void Execute(JobContext Job, HashSet<FileReference> BuildProducts, Dictionary<string, HashSet<FileReference>> TagNameToFileSet) { // Parse all the source patterns FilePattern SourcePattern = new FilePattern(CommandUtils.RootDirectory, Parameters.From); // Parse the target pattern FilePattern TargetPattern = new FilePattern(CommandUtils.RootDirectory, Parameters.To); // Apply the filter to the source files HashSet<FileReference> Files = null; if(!String.IsNullOrEmpty(Parameters.Files)) { SourcePattern = SourcePattern.AsDirectoryPattern(); Files = ResolveFilespec(SourcePattern.BaseDirectory, Parameters.Files, TagNameToFileSet); } // Build the file mapping Dictionary<FileReference, FileReference> TargetFileToSourceFile = FilePattern.CreateMapping(Files, SourcePattern, TargetPattern); // Check we got some files if(TargetFileToSourceFile.Count == 0) { CommandUtils.Log("No files found matching '{0}'", SourcePattern); return; } // If the target is on a network share, retry creating the first directory until it succeeds DirectoryReference FirstTargetDirectory = TargetFileToSourceFile.First().Key.Directory; if(!DirectoryReference.Exists(FirstTargetDirectory)) { const int MaxNumRetries = 15; for(int NumRetries = 0;;NumRetries++) { try { DirectoryReference.CreateDirectory(FirstTargetDirectory); if(NumRetries == 1) { Log.TraceInformation("Created target directory {0} after 1 retry.", FirstTargetDirectory); } else if(NumRetries > 1) { Log.TraceInformation("Created target directory {0} after {1} retries.", FirstTargetDirectory, NumRetries); } break; } catch(Exception Ex) { if(NumRetries == 0) { Log.TraceInformation("Unable to create directory '{0}' on first attempt. Retrying {1} times...", FirstTargetDirectory, MaxNumRetries); } Log.TraceLog(" {0}", Ex); if(NumRetries >= 15) { throw new AutomationException(Ex, "Unable to create target directory '{0}' after {1} retries.", FirstTargetDirectory, NumRetries); } Thread.Sleep(2000); } } } // Copy them all KeyValuePair<FileReference, FileReference>[] FilePairs = TargetFileToSourceFile.ToArray(); CommandUtils.Log("Copying {0} file{1} from {2} to {3}...", FilePairs.Length, (FilePairs.Length == 1)? "" : "s", SourcePattern.BaseDirectory, TargetPattern.BaseDirectory); CommandUtils.ThreadedCopyFiles(FilePairs.Select(x => x.Value.FullName).ToList(), FilePairs.Select(x => x.Key.FullName).ToList(), bQuiet: true); // Update the list of build products BuildProducts.UnionWith(TargetFileToSourceFile.Keys); // Apply the optional output tag to them foreach(string TagName in FindTagNamesFromList(Parameters.Tag)) { FindOrAddTagSet(TagNameToFileSet, TagName).UnionWith(TargetFileToSourceFile.Keys); } }