You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
Nodes can now be implemented by arbitary C# methods. Graph structure is specified through expression trees implemented using Bg* types, which are not substituted with values until execution time. Doing so allows determination of node and option dependencies for a particular target, allowing us to generate dynamic UI for presenting relevant settings to the user. Includes partial implementation of Installed Build script as an example implementation. #preflight 61bb85d46c2686e86322eec9 [CL 18477305 by Ben Marsh in ue5-main branch]
233 lines
7.0 KiB
C#
233 lines
7.0 KiB
C#
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
using AutomationTool;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Xml;
|
|
using EpicGames.Core;
|
|
using UnrealBuildTool;
|
|
using EpicGames.BuildGraph;
|
|
using AutomationTool.Tasks;
|
|
|
|
namespace AutomationTool.Tasks
|
|
{
|
|
/// <summary>
|
|
/// Parameters for a spawn task
|
|
/// </summary>
|
|
public class SpawnTaskParameters
|
|
{
|
|
/// <summary>
|
|
/// Executable to spawn.
|
|
/// </summary>
|
|
[TaskParameter]
|
|
public string Exe;
|
|
|
|
/// <summary>
|
|
/// Arguments for the newly created process.
|
|
/// </summary>
|
|
[TaskParameter(Optional = true)]
|
|
public string Arguments;
|
|
|
|
/// <summary>
|
|
/// Working directory for spawning the new task
|
|
/// </summary>
|
|
[TaskParameter(Optional = true)]
|
|
public string WorkingDir;
|
|
|
|
/// <summary>
|
|
/// Environment variables to set
|
|
/// </summary>
|
|
[TaskParameter(Optional = true)]
|
|
public string Environment;
|
|
|
|
/// <summary>
|
|
/// File to read environment from
|
|
/// </summary>
|
|
[TaskParameter(Optional = true)]
|
|
public string EnvironmentFile;
|
|
|
|
/// <summary>
|
|
/// Write output to the log
|
|
/// </summary>
|
|
[TaskParameter(Optional = true)]
|
|
public bool LogOutput = true;
|
|
|
|
/// <summary>
|
|
/// The minimum exit code, which is treated as an error.
|
|
/// </summary>
|
|
[TaskParameter(Optional = true)]
|
|
public int ErrorLevel = 1;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Base class for tasks that run an external tool
|
|
/// </summary>
|
|
public abstract class SpawnTaskBase : BgTaskImpl
|
|
{
|
|
/// <summary>
|
|
/// Execute a command
|
|
/// </summary>
|
|
protected static Task<IProcessResult> ExecuteAsync(string Exe, string Arguments, string WorkingDir = null, Dictionary<string, string> EnvVars = null, bool LogOutput = true, int ErrorLevel = 1, string Input = null)
|
|
{
|
|
if (WorkingDir != null)
|
|
{
|
|
WorkingDir = ResolveDirectory(WorkingDir).FullName;
|
|
}
|
|
|
|
CommandUtils.ERunOptions Options = CommandUtils.ERunOptions.Default;
|
|
if (!LogOutput)
|
|
{
|
|
Options &= ~CommandUtils.ERunOptions.AllowSpew;
|
|
}
|
|
|
|
IProcessResult Result = CommandUtils.Run(Exe, Arguments, Env: EnvVars, WorkingDir: WorkingDir, Options: Options, Input: Input);
|
|
if (Result.ExitCode < 0 || Result.ExitCode >= ErrorLevel)
|
|
{
|
|
throw new AutomationException("{0} terminated with an exit code indicating an error ({1})", Path.GetFileName(Exe), Result.ExitCode);
|
|
}
|
|
|
|
return Task.FromResult(Result);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Parses environment from a property and file
|
|
/// </summary>
|
|
/// <param name="Environment"></param>
|
|
/// <param name="EnvironmentFile"></param>
|
|
/// <returns></returns>
|
|
protected static Dictionary<string, string> ParseEnvVars(string Environment, string EnvironmentFile)
|
|
{
|
|
Dictionary<string, string> EnvVars = new Dictionary<string, string>();
|
|
if (Environment != null)
|
|
{
|
|
ParseEnvironment(Environment, ';', EnvVars);
|
|
}
|
|
if (EnvironmentFile != null)
|
|
{
|
|
ParseEnvironment(FileUtils.ReadAllText(ResolveFile(EnvironmentFile)), '\n', EnvVars);
|
|
}
|
|
return EnvVars;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Parse environment from a string
|
|
/// </summary>
|
|
/// <param name="Environment"></param>
|
|
/// <param name="Separator"></param>
|
|
/// <param name="EnvVars"></param>
|
|
static void ParseEnvironment(string Environment, char Separator, Dictionary<string, string> EnvVars)
|
|
{
|
|
for (int BaseIdx = 0; BaseIdx < Environment.Length;)
|
|
{
|
|
int EqualsIdx = Environment.IndexOf('=', BaseIdx);
|
|
if (EqualsIdx == -1)
|
|
{
|
|
throw new AutomationException("Missing value in environment variable string '{0}'", Environment);
|
|
}
|
|
|
|
int EndIdx = Environment.IndexOf(Separator, EqualsIdx + 1);
|
|
if (EndIdx == -1)
|
|
{
|
|
EndIdx = Environment.Length;
|
|
}
|
|
|
|
string Name = Environment.Substring(BaseIdx, EqualsIdx - BaseIdx).Trim();
|
|
string Value = Environment.Substring(EqualsIdx + 1, EndIdx - (EqualsIdx + 1)).Trim();
|
|
EnvVars[Name] = Value;
|
|
|
|
BaseIdx = EndIdx + 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Spawns an external executable and waits for it to complete.
|
|
/// </summary>
|
|
[TaskElement("Spawn", typeof(SpawnTaskParameters))]
|
|
public class SpawnTask : SpawnTaskBase
|
|
{
|
|
/// <summary>
|
|
/// Parameters for this task
|
|
/// </summary>
|
|
SpawnTaskParameters Parameters;
|
|
|
|
/// <summary>
|
|
/// Construct a spawn task
|
|
/// </summary>
|
|
/// <param name="InParameters">Parameters for the task</param>
|
|
public SpawnTask(SpawnTaskParameters InParameters)
|
|
{
|
|
Parameters = InParameters;
|
|
}
|
|
|
|
/// <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 async Task ExecuteAsync(JobContext Job, HashSet<FileReference> BuildProducts, Dictionary<string, HashSet<FileReference>> TagNameToFileSet)
|
|
{
|
|
await ExecuteAsync(Parameters.Exe, Parameters.Arguments, Parameters.WorkingDir, EnvVars: ParseEnvVars(Parameters.Environment, Parameters.EnvironmentFile), LogOutput: Parameters.LogOutput, ErrorLevel: Parameters.ErrorLevel);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Output this task out to an XML writer.
|
|
/// </summary>
|
|
public override void Write(XmlWriter Writer)
|
|
{
|
|
Write(Writer, Parameters);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Find all the tags which are used as inputs to this task
|
|
/// </summary>
|
|
/// <returns>The tag names which are read by this task</returns>
|
|
public override IEnumerable<string> FindConsumedTagNames()
|
|
{
|
|
yield break;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Find all the tags which are modified by this task
|
|
/// </summary>
|
|
/// <returns>The tag names which are modified by this task</returns>
|
|
public override IEnumerable<string> FindProducedTagNames()
|
|
{
|
|
yield break;
|
|
}
|
|
}
|
|
|
|
public static partial class StandardTasks
|
|
{
|
|
/// <summary>
|
|
/// Execute an external program
|
|
/// </summary>
|
|
/// <param name="State">Execution state</param>
|
|
/// <param name="Exe">Executable to spawn.</param>
|
|
/// <param name="Arguments">Arguments for the newly created process.</param>
|
|
/// <param name="WorkingDir">Working directory for spawning the new task.</param>
|
|
/// <param name="Environment">Environment variables to set.</param>
|
|
/// <param name="EnvironmentFile">File to read environment from.</param>
|
|
/// <param name="LogOutput">Write output to the log.</param>
|
|
/// <param name="ErrorLevel">The minimum exit code which is treated as an error.</param>
|
|
public static async Task SpawnAsync(string Exe, string Arguments = null, string WorkingDir = null, string Environment = null, string EnvironmentFile = null, bool? LogOutput = null, int? ErrorLevel = null)
|
|
{
|
|
SpawnTaskParameters Parameters = new SpawnTaskParameters();
|
|
Parameters.Exe = Exe;
|
|
Parameters.Arguments = Arguments;
|
|
Parameters.WorkingDir = WorkingDir;
|
|
Parameters.Environment = Environment;
|
|
Parameters.EnvironmentFile = EnvironmentFile;
|
|
Parameters.LogOutput = LogOutput ?? Parameters.LogOutput;
|
|
Parameters.ErrorLevel = ErrorLevel ?? Parameters.ErrorLevel;
|
|
|
|
await ExecuteAsync(new SpawnTask(Parameters));
|
|
}
|
|
}
|
|
}
|