// Copyright Epic Games, Inc. All Rights Reserved. using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Xml; using EpicGames.Core; using UnrealBuildBase; using UnrealBuildTool; #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 { get; set; } /// /// Path to the output file to receive information about the targets /// [TaskParameter(Optional = true)] public FileReference? OutputFile { get; set; } = 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 { get; set; } = false; /// /// Tag to be applied to build products of this task. /// [TaskParameter(Optional = true, ValidationType = TaskParameterValidationType.TagList)] public string? Tag { get; set; } } /// /// Runs UBT to query all the targets for a particular project /// [TaskElement("QueryTargets", typeof(QueryTargetsTaskParameters))] public class QueryTargetsTask : BgTaskImpl { /// /// Parameters for this task /// readonly QueryTargetsTaskParameters _parameters; /// /// Construct a spawn task /// /// Parameters for the task public QueryTargetsTask(QueryTargetsTaskParameters parameters) { _parameters = parameters; } /// /// ExecuteAsync 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); } } }