// 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 OpenTracing;
using OpenTracing.Util;
namespace AutomationTool.Tasks
{
///
/// Parameters for a task that runs the cooker
///
public class CookTaskParameters
{
///
/// Project file to be cooked.
///
[TaskParameter]
public string Project { get; set; }
///
/// The cook platform to target (for example, Windows).
///
[TaskParameter]
public string Platform { get; set; }
///
/// List of maps to be cooked, separated by '+' characters.
///
[TaskParameter(Optional = true)]
public string Maps { get; set; }
///
/// Additional arguments to be passed to the cooker.
///
[TaskParameter(Optional = true)]
public bool Versioned { get; set; } = false;
///
/// Additional arguments to be passed to the cooker.
///
[TaskParameter(Optional = true)]
public string Arguments { get; set; } = "";
///
/// Optional path to what editor executable to run for cooking.
///
[TaskParameter(Optional = true)]
public string EditorExe { get; set; } = "";
///
/// Whether to tag the output from the cook. Since cooks produce a lot of files, it can be detrimental to spend time tagging them if we don't need them in a dependent node.
///
[TaskParameter(Optional = true)]
public bool TagOutput { get; set; } = true;
///
/// Tag to be applied to build products of this task.
///
[TaskParameter(Optional = true, ValidationType = TaskParameterValidationType.TagList)]
public string Tag { get; set; }
}
///
/// Cook a selection of maps for a certain platform
///
[TaskElement("Cook", typeof(CookTaskParameters))]
public class CookTask : BgTaskImpl
{
///
/// Parameters for the task
///
readonly CookTaskParameters _parameters;
///
/// Constructor.
///
/// Parameters for this task
public CookTask(CookTaskParameters 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)
{
// Figure out the project that this target belongs to
FileReference projectFile = null;
if (_parameters.Project != null)
{
projectFile = new FileReference(_parameters.Project);
if (!FileReference.Exists(projectFile))
{
throw new AutomationException("Missing project file - {0}", projectFile.FullName);
}
}
// ExecuteAsync the cooker
using (IScope scope = GlobalTracer.Instance.BuildSpan("Cook").StartActive())
{
scope.Span.SetTag("project", projectFile == null ? "UE4" : projectFile.GetFileNameWithoutExtension());
scope.Span.SetTag("platform", _parameters.Platform);
string[] maps = (_parameters.Maps == null) ? null : _parameters.Maps.Split(new char[] { '+' });
string arguments = (_parameters.Versioned ? "" : "-Unversioned ") + _parameters.Arguments;
string editorExe = (System.String.IsNullOrWhiteSpace(_parameters.EditorExe) ? ProjectUtils.GetEditorForProject(projectFile).FullName : _parameters.EditorExe);
CommandUtils.CookCommandlet(projectFile, editorExe, maps, null, null, null, _parameters.Platform, arguments);
}
// Find all the cooked files
List cookedFiles = new List();
if (_parameters.TagOutput)
{
foreach (string platform in _parameters.Platform.Split('+'))
{
DirectoryReference platformCookedDirectory = DirectoryReference.Combine(projectFile.Directory, "Saved", "Cooked", platform);
if (!DirectoryReference.Exists(platformCookedDirectory))
{
throw new AutomationException("Cook output directory not found ({0})", platformCookedDirectory.FullName);
}
List platformCookedFiles = DirectoryReference.EnumerateFiles(platformCookedDirectory, "*", System.IO.SearchOption.AllDirectories).ToList();
if (platformCookedFiles.Count == 0)
{
throw new AutomationException("Cooking did not produce any files in {0}", platformCookedDirectory.FullName);
}
cookedFiles.AddRange(platformCookedFiles);
}
}
// Apply the optional tag to the build products
foreach (string tagName in FindTagNamesFromList(_parameters.Tag))
{
FindOrAddTagSet(tagNameToFileSet, tagName).UnionWith(cookedFiles);
}
// Add them to the set of build products
buildProducts.UnionWith(cookedFiles);
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()
{
return FindTagNamesFromList(_parameters.Tag);
}
}
}