// Copyright Epic Games, Inc. All Rights Reserved. using AutomationTool; using AutomationTool.Tasks; using EpicGames.BuildGraph; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Xml; using EpicGames.Core; using UnrealBuildTool; using UnrealBuildBase; #nullable enable namespace AutomationTool.Tasks { /// /// Parameters to query for all the targets in a project /// public class QueryTargetsTaskParameters { /// /// Path to the project file to query /// [TaskParameter(Optional = true)] public FileReference? ProjectFile; /// /// Path to the output file to receive information about the targets /// [TaskParameter(Optional = true)] public FileReference? OutputFile = null; /// /// Write out all targets, even if a default is specified in the BuildSettings section of the Default*.ini files. /// [TaskParameter(Optional = true)] public bool IncludeAllTargets = false; /// /// Tag to be applied to build products of this task. /// [TaskParameter(Optional = true, ValidationType = TaskParameterValidationType.TagList)] public string? Tag; } /// /// Runs UBT to query all the targets for a particular project /// [TaskElement("QueryTargets", typeof(QueryTargetsTaskParameters))] public class QueryTargetsTask : BgTaskImpl { /// /// Parameters for this task /// QueryTargetsTaskParameters Parameters; /// /// Construct a spawn task /// /// Parameters for the task public QueryTargetsTask(QueryTargetsTaskParameters InParameters) { Parameters = InParameters; } /// /// Execute the task. /// /// Information about the current job /// Set of build products produced by this node. /// Mapping from tag names to the set of files they include public override Task ExecuteAsync(JobContext Job, HashSet BuildProducts, Dictionary> TagNameToFileSet) { // Get the output file FileReference? OutputFile = Parameters.OutputFile; if (OutputFile == null) { if (Parameters.ProjectFile == null) { OutputFile = FileReference.Combine(Unreal.EngineDirectory, "Intermediate", "TargetInfo.json"); } else { OutputFile = FileReference.Combine(Parameters.ProjectFile.Directory, "Intermediate", "TargetInfo.json"); } } FileUtils.ForceDeleteFile(OutputFile); // Run UBT to generate the target info List Arguments = new List { "-Mode=QueryTargets" }; if (Parameters.ProjectFile != null) { Arguments.Add($"-Project={Parameters.ProjectFile}"); } if (Parameters.IncludeAllTargets) { Arguments.Add("-IncludeAllTargets"); } CommandUtils.RunUBT(CommandUtils.CmdEnv, Unreal.UnrealBuildToolDllPath, CommandLineArguments.Join(Arguments)); // Check the output file exists if (!FileReference.Exists(OutputFile)) { throw new BuildException($"Missing {OutputFile}"); } // Apply the optional tag to the build products foreach(string TagName in FindTagNamesFromList(Parameters.Tag)) { FindOrAddTagSet(TagNameToFileSet, TagName).Add(OutputFile); } // Add the target files to the set of build products BuildProducts.Add(OutputFile); return Task.CompletedTask; } /// /// Output this task out to an XML writer. /// public override void Write(XmlWriter Writer) { Write(Writer, Parameters); } /// /// Find all the tags which are used as inputs to this task /// /// The tag names which are read by this task public override IEnumerable FindConsumedTagNames() { return Enumerable.Empty(); } /// /// Find all the tags which are modified by this task /// /// The tag names which are modified by this task public override IEnumerable FindProducedTagNames() { return FindTagNamesFromList(Parameters.Tag); } } }