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

211 lines
8.2 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using UnityEditor.Build.Content;
using UnityEditor.Build.Pipeline.Utilities;
[assembly: InternalsVisibleTo("Unity.Addressables.Editor.Tests")]
namespace UnityEditor.Build.Pipeline.Interfaces
{
/// <summary>
/// Describes the level of a log entry
/// </summary>
public enum LogLevel
{
/// <summary>
/// The entry is reporting an error.
/// </summary>
Error,
/// <summary>
/// The entry is reporting an warning.
/// </summary>
Warning,
/// <summary>
/// The entry is reporting general information.
/// </summary>
Info,
/// <summary>
/// The entry is reporting verbose information.
/// </summary>
Verbose
}
/// <summary>
/// Interface for monitoring the build process. Several tasks will log details of their progress through this interface.
/// See the [Build Logging](https://docs.unity3d.com/Packages/com.unity.scriptablebuildpipeline@latest/index.html?subfolder=/manual/BuildLogger.html) documentation for more details.
/// </summary>
public interface IBuildLogger : IContextObject
{
/// <summary>
/// Adds details to the active build step
/// </summary>
/// <param name="level">The log level of this entry.</param>
/// <param name="msg">The message to add.</param>
void AddEntry(LogLevel level, string msg);
/// <summary>
/// Should be called when beginning a build step.
/// </summary>
/// <param name="level">The log level of this step.</param>
/// <param name="stepName">A name associated with the step. It is recommended that this name does not include specific context about the step; dynamic context should be added under the step as an entry.</param>
/// <param name="subStepsCanBeThreaded">True if within this build step the IBuildLogger will be used on multiple threads.</param>
void BeginBuildStep(LogLevel level, string stepName, bool subStepsCanBeThreaded);
/// <summary>
/// Ends the build step.
/// </summary>
void EndBuildStep();
}
internal enum DeferredEventType
{
Begin,
End,
Info
}
internal struct DeferredEvent
{
public LogLevel Level;
public DeferredEventType Type;
public double Time;
public string Name;
public string Context;
}
internal interface IDeferredBuildLogger
{
void HandleDeferredEventStream(IEnumerable<DeferredEvent> events);
}
/// <summary>
/// Helper class to define a scope with a using statement
/// </summary>
public struct ScopedBuildStep : IDisposable
{
IBuildLogger m_Logger;
internal ScopedBuildStep(LogLevel level, string stepName, IBuildLogger logger, bool multiThreaded, string context)
{
m_Logger = logger;
m_Logger?.BeginBuildStep(level, stepName, multiThreaded);
if (!string.IsNullOrEmpty(context))
m_Logger?.AddEntrySafe(level, context);
}
/// <inheritdoc/>
void IDisposable.Dispose()
{
m_Logger?.EndBuildStep();
}
}
#if UNITY_2020_2_OR_NEWER || ENABLE_DETAILED_PROFILE_CAPTURING
internal struct ProfileCaptureScope : IDisposable
{
IBuildLogger m_Logger;
public ProfileCaptureScope(IBuildLogger logger, ProfileCaptureOptions options)
{
m_Logger = ScriptableBuildPipeline.useDetailedBuildLog ? logger : null;
ContentBuildInterface.StartProfileCapture(options);
}
public void Dispose()
{
ContentBuildProfileEvent[] events = ContentBuildInterface.StopProfileCapture();
if (m_Logger == null)
return;
IDeferredBuildLogger dLog = (IDeferredBuildLogger)m_Logger;
IEnumerable<DeferredEvent> dEvents = events.Select(i =>
{
var e = new DeferredEvent();
e.Level = LogLevel.Verbose;
BuildLoggerExternsions.ConvertNativeEventName(i.Name, out e.Name, out e.Context);
e.Time = (double)i.TimeMicroseconds / (double)1000;
e.Type = BuildLoggerExternsions.ConvertToDeferredType(i.Type);
return e;
});
dLog.HandleDeferredEventStream(dEvents);
}
}
#endif
/// <summary>
/// Contains extension methods for the IBuildLogger interface
/// </summary>
public static class BuildLoggerExternsions
{
/// <summary>
/// Adds details to the active build step
/// </summary>
/// <param name="log">The build log.</param>
/// <param name="level">The log level of this entry.</param>
/// <param name="msg">The message to add.</param>
public static void AddEntrySafe(this IBuildLogger log, LogLevel level, string msg)
{
if (log != null)
{
log.AddEntry(level, msg);
}
}
/// <summary>
/// Begins a new build step and returns an ScopedBuildStep which will end the build step when disposed. It is recommended to use this in conjunction with the using statement.
/// </summary>
/// <param name="log">The build log.</param>
/// <param name="level">The log level of this step.</param>
/// <param name="stepName">A name associated with the step.</param>
/// <param name="multiThreaded">True if within this build step the IBuildLogger will be used on multiple threads.</param>
/// <returns>Returns a ScopedBuildStep that will end the build step when it is disposed.</returns>
public static ScopedBuildStep ScopedStep(this IBuildLogger log, LogLevel level, string stepName, bool multiThreaded = false)
{
return new ScopedBuildStep(level, stepName, log, multiThreaded, null);
}
/// <summary>
/// Begins a new build step and returns an ScopedBuildStep which will end the build step when disposed. It is recommended to use this in conjunction with the using statement.
/// </summary>
/// <param name="log">The build log.</param>
/// <param name="level">The log level of this step.</param>
/// <param name="stepName">A name associated with the step.</param>
/// <param name="context">Adds an entry message the build step. This allows attaching specific context data without changing the stepName.</param>
/// <returns>Returns a ScopedBuildStep that will end the build step when it is disposed.</returns>
public static ScopedBuildStep ScopedStep(this IBuildLogger log, LogLevel level, string stepName, string context)
{
return new ScopedBuildStep(level, stepName, log, false, context);
}
#if UNITY_2020_2_OR_NEWER || ENABLE_DETAILED_PROFILE_CAPTURING
internal static DeferredEventType ConvertToDeferredType(ProfileEventType type)
{
if (type == ProfileEventType.Begin) return DeferredEventType.Begin;
if (type == ProfileEventType.End) return DeferredEventType.End;
if (type == ProfileEventType.Info) return DeferredEventType.Info;
throw new Exception("Unknown type");
}
const string k_WriteFile = "Write file:";
const string k_WriteObject = "Write object - ";
internal static void ConvertNativeEventName(string nativeName, out string eventName, out string eventContext)
{
eventName = nativeName;
eventContext = "";
if (nativeName.StartsWith(k_WriteFile, StringComparison.Ordinal))
{
eventName = "Write File";
eventContext = nativeName.Substring(k_WriteFile.Length);
}
else if (nativeName.StartsWith(k_WriteObject, StringComparison.Ordinal))
{
eventName = "Write Object";
eventContext = nativeName.Substring(k_WriteObject.Length);
}
if (eventContext.Any(c => c == '"'))
eventContext = eventContext.Replace("\"", "\\\"");
}
#endif
}
}