// Copyright Epic Games, Inc. All Rights Reserved. using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using EpicGames.Core; using UnrealBuildBase; using UnrealBuildTool; using Microsoft.Extensions.Logging; namespace AutomationTool.Benchmark { [Flags] public enum UBTBuildOptions { None = 0, PreClean = 1 << 0, // don't preclean before the job (useful for testing) PostClean = 1 << 1, // clean after the job (default for building multiple clients) CleanOnly = 1 << 2, } [Flags] public enum DDCTaskOptions { None = 0, WarmDDC = 1 << 0, ColdDDCNoShared = 1 << 1, ColdDDC = 1 << 2, NoShaderDDC = 1 << 3, HotDDC = 1 << 4, KeepMemoryDDC = 1 << 6, } [Flags] public enum XGETaskOptions { None = 0, NoXGE = 1 << 1, WithXGE = 1 << 2, NoEditorXGE = 1 << 3, // don't use XGE for shader compilation WithEditorXGE = 1 << 4, // don't use XGE for shader compilation } /// /// Simple class that describes a target in a project /// class ProjectTargetInfo { public FileReference ProjectFile { get; private set; } public UnrealTargetPlatform TargetPlatform { get; private set; } public bool BuildTargetAsClient { get; private set; } public ProjectTargetInfo(FileReference InFileReference, UnrealTargetPlatform InTargetPlatform, bool InBuildTargetAsClient) { ProjectFile = InFileReference; TargetPlatform = InTargetPlatform; BuildTargetAsClient = InBuildTargetAsClient; } } /// /// Base class for running tasks /// abstract class BenchmarkTaskBase { /// /// Default logger instance /// protected static ILogger Logger => Log.Logger; /// /// True or false based on whether the task failed /// public bool Failed { get; protected set; } /// /// Failure message /// public string FailureString { get; protected set; } /// /// Don't report this test /// public bool SkipReport { get; set; } /// /// Time the task took (does not include prequisites) /// public TimeSpan TaskTime { get; protected set; } /// /// Time the task started /// public DateTime StartTime { get; protected set; } /// /// Perform any prerequisites the task requires /// virtual protected bool PerformPrequisites() { return true; } /// /// Perform post-task cleanup /// virtual protected void PerformCleanup() { } /// /// Perform the actual task that is measured /// protected abstract bool PerformTask(); /// /// Path to the project file we're using. May be null for Unreal editor, client etc /// public FileReference ProjectFile { get; private set; } /// /// Return the name of the module this is being performed on /// /// public string ProjectName { get { return ProjectFile == null ? "Unreal" : ProjectFile.GetFileNameWithoutAnyExtensions(); } } /// /// Return the name of this task /// /// public abstract string TaskName { get; } private readonly List InternalModifiers = new List(); /// /// A list of modifiers that can be considered when /// protected List TaskModifiers { get { return InternalModifiers; } } /// /// Return the full name of this task for reporting /// /// public string ModifierString { get { string Str = String.Empty; if (TaskModifiers.Count > 0) { Str = string.Join(" ", TaskModifiers); } return Str; } } /// /// Returns a full name to use in reporting and logging /// /// public string TaskNameWithModifiers { get { string Name = TaskName; if (TaskModifiers.Count > 0) { Name = string.Format("{0} ({1})", Name, ModifierString); } return Name; } } /// /// Return the full name of this task for reporting /// /// public string FullName { get { return String.Format("{0} {1}", ProjectName, TaskNameWithModifiers); } } /// /// Simple constructor /// /// public BenchmarkTaskBase(FileReference InProjectFile) { ProjectFile = InProjectFile; } /// /// Run the task. Performs any prerequisites, then the actual task itself /// public void Run() { try { if (PerformPrequisites()) { StartTime = DateTime.Now; if (!PerformTask()) { FailureString = "Task Failed"; Failed = true; } } else { FailureString = "Prequisites Failed"; Failed = true; } } catch (Exception Ex) { FailureString = string.Format("Exception: {0}", Ex.ToString()); Failed = true; } if (StartTime != DateTime.MinValue) { TaskTime = DateTime.Now - StartTime; } if (Failed) { Logger.LogError("{FullName} failed. {FailureString}", FullName, FailureString); } try { PerformCleanup(); } catch (Exception Ex) { Logger.LogError("Cleanup of {FullName} failed. {Ex}", FullName, Ex); } } /// /// Report how long the task took /// public void Report() { if (!Failed) { Logger.LogInformation("Task {FullName}:\t\t\t\t{Arg1}", FullName, TaskTime.ToString(@"hh\:mm\:ss")); } else { Logger.LogInformation("Task {FullName}::\t\t\t\t{Arg1} Failed. {FailureString}", FullName, TaskTime.ToString(@"hh\:mm\:ss"), FailureString); } } public override string ToString() { return FullName; } } }