WuhuIslandTesting/Library/PackageCache/com.unity.scriptablebuildpipeline@1.21.5/Editor/Shared/BuildTasksRunner.cs
2025-01-07 02:06:59 +01:00

186 lines
7.8 KiB
C#

using System;
using System.Collections.Generic;
using UnityEditor.Build.Pipeline.Injector;
using UnityEditor.Build.Pipeline.Interfaces;
using UnityEditor.Build.Pipeline.Utilities;
using UnityEditor.Build.Profiler;
using UnityEditor.Build.Reporting;
namespace UnityEditor.Build.Pipeline
{
/// <summary>
/// Basic static class containing default implementations for BuildTask validation and running.
/// </summary>
public static class BuildTasksRunner
{
/// <summary>
/// Basic run implementation that takes a set of tasks, a context, and runs returning the build results.
/// <seealso cref="IBuildTask"/>, <seealso cref="IBuildContext"/>, and <seealso cref="ReturnCode"/>
/// </summary>
/// <param name="pipeline">The set of build tasks to run.</param>
/// <param name="context">The build context to use for this run.</param>
/// <returns>Return code with status information about success or failure causes.</returns>
public static ReturnCode Run(IList<IBuildTask> pipeline, IBuildContext context)
{
// Avoid throwing exceptions in here as we don't want them bubbling up to calling user code
if (pipeline == null)
{
BuildLogger.LogException(new ArgumentNullException("pipeline"));
return ReturnCode.Exception;
}
// Avoid throwing exceptions in here as we don't want them bubbling up to calling user code
if (context == null)
{
BuildLogger.LogException(new ArgumentNullException("context"));
return ReturnCode.Exception;
}
IProgressTracker tracker;
if (context.TryGetContextObject(out tracker))
tracker.TaskCount = pipeline.Count;
context.TryGetContextObject(out IBuildLogger logger);
foreach (IBuildTask task in pipeline)
{
{
try
{
if (!tracker.UpdateTaskUnchecked(task.GetType().Name.HumanReadable()))
return ReturnCode.Canceled;
ContextInjector.Inject(context, task);
ReturnCode result;
using (logger.ScopedStep(LogLevel.Info, task.GetType().Name))
result = task.Run();
if (result < ReturnCode.Success)
return result;
ContextInjector.Extract(context, task);
}
catch (Exception e)
{
BuildLogger.LogError("Build Task {0} failed with exception:\n{1}\n{2}", task.GetType().Name, e.Message, e.StackTrace);
return ReturnCode.Exception;
}
}
}
if (tracker is IDisposable disposable)
disposable.Dispose();
return ReturnCode.Success;
}
/// <summary>
/// Run implementation with task profiler that takes a set of tasks, a context, runs returning the build results and prints out the profiler details.
/// <seealso cref="IBuildTask"/>, <seealso cref="IBuildContext"/>, and <seealso cref="ReturnCode"/>
/// </summary>
/// <param name="pipeline">The set of build tasks to run.</param>
/// <param name="context">The build context to use for this run.</param>
/// <returns>Return code with status information about success or failure causes.</returns>
internal static ReturnCode RunProfiled(IList<IBuildTask> pipeline, IBuildContext context)
{
// Avoid throwing exceptions in here as we don't want them bubbling up to calling user code
if (pipeline == null)
{
BuildLogger.LogException(new ArgumentNullException("pipeline"));
return ReturnCode.Exception;
}
// Avoid throwing exceptions in here as we don't want them bubbling up to calling user code
if (context == null)
{
BuildLogger.LogException(new ArgumentNullException("context"));
return ReturnCode.Exception;
}
var profiler = new BuildProfiler(pipeline.Count + 1);
profiler.Start(pipeline.Count, "TotalTime");
int count = 0;
IProgressTracker tracker;
if (context.TryGetContextObject(out tracker))
tracker.TaskCount = pipeline.Count;
foreach (IBuildTask task in pipeline)
{
try
{
if (!tracker.UpdateTaskUnchecked(task.GetType().Name.HumanReadable()))
{
profiler.Stop(pipeline.Count);
profiler.Print();
return ReturnCode.Canceled;
}
ContextInjector.Inject(context, task);
profiler.Start(count, task.GetType().Name);
var result = task.Run();
profiler.Stop(count++);
if (result < ReturnCode.Success)
{
profiler.Stop(pipeline.Count);
profiler.Print();
return result;
}
ContextInjector.Extract(context, task);
}
catch (Exception e)
{
BuildLogger.LogException(e);
profiler.Stop(count);
profiler.Print();
return ReturnCode.Exception;
}
}
profiler.Stop(pipeline.Count);
profiler.Print();
return ReturnCode.Success;
}
/// <summary>
/// Basic validate implementation that takes a set of tasks, a context, and does checks to ensure the task requirements are all satisfied.
/// <seealso cref="IBuildTask"/>, <seealso cref="IBuildContext"/>, and <seealso cref="ReturnCode"/>
/// </summary>
/// <param name="pipeline">The set of build tasks to run.</param>
/// <param name="context">The build context to use for this run.</param>
/// <returns>Return code with status information about success or failure causes.</returns>
public static ReturnCode Validate(IList<IBuildTask> pipeline, IBuildContext context)
{
//// Avoid throwing exceptions in here as we don't want them bubbling up to calling user code
//if (pipeline == null)
//{
// BuildLogger.LogException(new ArgumentNullException("pipeline"));
// return ReturnCode.Exception;
//}
//// Avoid throwing exceptions in here as we don't want them bubbling up to calling user code
//if (context == null)
//{
// BuildLogger.LogException(new ArgumentNullException("context"));
// return ReturnCode.Exception;
//}
//var requiredTypes = new HashSet<Type>();
//foreach (IBuildTask task in pipeline)
// requiredTypes.UnionWith(task.RequiredContextTypes);
//var missingTypes = new List<string>();
//foreach (Type requiredType in requiredTypes)
//{
// if (!context.ContainsContextObject(requiredType))
// missingTypes.Add(requiredType.Name);
//}
//if (missingTypes.Count > 0)
//{
// BuildLogger.LogError("Missing required object types to run build pipeline:\n{0}", string.Join(", ", missingTypes.ToArray()));
// return ReturnCode.MissingRequiredObjects;
//}
return ReturnCode.Success;
}
}
}