// Copyright Epic Games, Inc. All Rights Reserved. using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Xml; using EpicGames.BuildGraph; using EpicGames.Core; using UnrealBuildTool; namespace AutomationTool.Tasks { /// /// Parameters for a task which runs a UE commandlet /// public class CommandletTaskParameters { /// /// The commandlet name to execute. /// [TaskParameter] public string Name { get; set; } /// /// The project to run the editor with. /// [TaskParameter(Optional = true, ValidationType = TaskParameterValidationType.FileSpec)] public string Project { get; set; } /// /// Arguments to be passed to the commandlet. /// [TaskParameter(Optional = true)] public string Arguments { get; set; } /// /// The editor executable to use. Defaults to the development UnrealEditor executable for the current platform. /// [TaskParameter(Optional = true)] public FileReference EditorExe { get; set; } /// /// The minimum exit code, which is treated as an error. /// [TaskParameter(Optional = true)] public int ErrorLevel { get; set; } = 1; } /// /// Spawns the editor to run a commandlet. /// [TaskElement("Commandlet", typeof(CommandletTaskParameters))] public class CommandletTask : BgTaskImpl { readonly CommandletTaskParameters _parameters; /// /// Construct a new CommandletTask. /// /// Parameters for this task public CommandletTask(CommandletTaskParameters 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 full path to the project file FileReference projectFile = null; if (!String.IsNullOrEmpty(_parameters.Project)) { if (_parameters.Project.EndsWith(".uproject", StringComparison.OrdinalIgnoreCase)) { projectFile = ResolveFile(_parameters.Project); } else { projectFile = NativeProjects.EnumerateProjectFiles(Log.Logger).FirstOrDefault(x => x.GetFileNameWithoutExtension().Equals(_parameters.Project, StringComparison.OrdinalIgnoreCase)); } if (projectFile == null || !FileReference.Exists(projectFile)) { throw new BuildException("Unable to resolve project '{0}'", _parameters.Project); } } // Get the path to the editor, and check it exists FileSystemReference editorExe = _parameters.EditorExe; if (editorExe == null) { editorExe = ProjectUtils.GetEditorForProject(projectFile); } // Run the commandlet CommandUtils.RunCommandlet(projectFile, editorExe.FullName, _parameters.Name, _parameters.Arguments, _parameters.ErrorLevel); 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() { yield break; } /// /// Find all the tags which are modified by this task /// /// The tag names which are modified by this task public override IEnumerable FindProducedTagNames() { yield break; } } /// /// Task wrapper methods /// public static partial class StandardTasks { /// /// Task which runs a UE commandlet /// /// /// The commandlet name to execute. /// The project to run the editor with. /// Arguments to be passed to the commandlet. /// The editor executable to use. Defaults to the development UnrealEditor executable for the current platform. /// The minimum exit code, which is treated as an error. public static async Task CommandletAsync(this BgContext state, string name, FileReference project = null, string arguments = null, FileReference editorExe = null, int errorLevel = 1) { _ = state; CommandletTaskParameters parameters = new CommandletTaskParameters(); parameters.Name = name; parameters.Project = project?.FullName; parameters.Arguments = arguments; parameters.EditorExe = editorExe; parameters.ErrorLevel = errorLevel; await ExecuteAsync(new CommandletTask(parameters)); } } }