Files
UnrealEngine/Engine/Source/Developer/DerivedDataCache/Public/DerivedDataBuildOutput.h
2025-05-18 13:04:45 +08:00

278 lines
8.9 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "Containers/ArrayView.h"
#include "Containers/ContainersFwd.h"
#include "Containers/StringFwd.h"
#include "Containers/StringView.h"
#include "CoreTypes.h"
#include "Misc/ScopeExit.h"
#include "Templates/RefCounting.h"
#include "Templates/UniquePtr.h"
#include "Templates/UnrealTemplate.h"
#define UE_API DERIVEDDATACACHE_API
class FCbField;
class FCbObject;
class FCbWriter;
namespace UE::DerivedData { class FBuildOutput; }
namespace UE::DerivedData { class FBuildOutputBuilder; }
namespace UE::DerivedData { class FCacheRecord; }
namespace UE::DerivedData { class FCacheRecordBuilder; }
namespace UE::DerivedData { class FOptionalBuildOutput; }
namespace UE::DerivedData { class FValue; }
namespace UE::DerivedData { class FValueWithId; }
namespace UE::DerivedData { struct FBuildOutputLog; }
namespace UE::DerivedData { struct FBuildOutputMessage; }
namespace UE::DerivedData { struct FValueId; }
namespace UE::DerivedData::Private
{
class IBuildOutputInternal
{
public:
virtual ~IBuildOutputInternal() = default;
virtual const FSharedString& GetName() const = 0;
virtual const FUtf8SharedString& GetFunction() const = 0;
virtual const FCbObject& GetMeta() const = 0;
virtual bool FindMeta(FUtf8StringView Key, FCbField& OutMeta) const = 0;
virtual const FValueWithId& GetValue(const FValueId& Id) const = 0;
virtual TConstArrayView<FValueWithId> GetValues() const = 0;
virtual TConstArrayView<FBuildOutputMessage> GetMessages() const = 0;
virtual TConstArrayView<FBuildOutputLog> GetLogs() const = 0;
virtual bool HasLogs() const = 0;
virtual bool HasError() const = 0;
virtual void Save(FCbWriter& Writer) const = 0;
virtual void Save(FCacheRecordBuilder& RecordBuilder) const = 0;
virtual void AddRef() const = 0;
virtual void Release() const = 0;
};
FBuildOutput CreateBuildOutput(IBuildOutputInternal* Output);
class IBuildOutputBuilderInternal
{
public:
virtual ~IBuildOutputBuilderInternal() = default;
virtual void AddMeta(FUtf8StringView Key, const FCbField& Meta) = 0;
virtual void AddValue(const FValueId& Id, const FValue& Value) = 0;
virtual void AddMessage(const FBuildOutputMessage& Message) = 0;
virtual void AddLog(const FBuildOutputLog& Log) = 0;
virtual bool HasError() const = 0;
virtual FBuildOutput Build() = 0;
};
FBuildOutputBuilder CreateBuildOutputBuilder(IBuildOutputBuilderInternal* OutputBuilder);
} // UE::DerivedData::Private
namespace UE::DerivedData
{
enum class EBuildOutputMessageLevel : uint8
{
Error,
Warning,
Display,
};
UE_API FUtf8StringBuilderBase& operator<<(FUtf8StringBuilderBase& Builder, EBuildOutputMessageLevel Level);
/** A build output message is diagnostic output from a build function and must be deterministic. */
struct FBuildOutputMessage
{
FUtf8StringView Message;
EBuildOutputMessageLevel Level;
};
enum class EBuildOutputLogLevel : uint8
{
Error,
Warning,
};
UE_API FUtf8StringBuilderBase& operator<<(FUtf8StringBuilderBase& Builder, EBuildOutputLogLevel Level);
/**
* A build output log is a log message captured from a build function.
*
* The build function may capture every log above a certain level of verbosity, which means these
* have no guarantee of being deterministic. The presence of any output logs will disable caching
* of the build output. To allow caching of build output with warnings or errors, replace the log
* statements with build messages that are added to the build context.
*/
struct FBuildOutputLog
{
FUtf8StringView Category;
FUtf8StringView Message;
EBuildOutputLogLevel Level;
};
/**
* A build output is an immutable container of values, messages, and logs produced by a build.
*
* The output will not contain any values if it has any errors.
*
* The output can be requested without data, which means that the values will have null data.
*/
class FBuildOutput
{
public:
/** Returns the name by which to identify this output for logging and profiling. */
inline const FSharedString& GetName() const { return Output->GetName(); }
/** Returns the name of the build function that produced this output. */
inline const FUtf8SharedString& GetFunction() const { return Output->GetFunction(); }
/** Returns the optional metadata. */
inline const FCbObject& GetMeta() const { return Output->GetMeta(); }
/** Finds the metadata matching the key. Returns true if found. */
inline bool FindMeta(FUtf8StringView Key, FCbField& OutMeta) const { return Output->FindMeta(Key, OutMeta); }
/** Returns the value matching the ID. Null if no match. Buffer is null if skipped. */
inline const FValueWithId& GetValue(const FValueId& Id) const { return Output->GetValue(Id); }
/** Returns the values in the output in order by ID. */
inline TConstArrayView<FValueWithId> GetValues() const { return Output->GetValues(); }
/** Returns the messages in the order that they were recorded. */
inline TConstArrayView<FBuildOutputMessage> GetMessages() const { return Output->GetMessages(); }
/** Returns the logs in the order that they were recorded. */
inline TConstArrayView<FBuildOutputLog> GetLogs() const { return Output->GetLogs(); }
/** Returns whether the output has any logs. */
inline bool HasLogs() const { return Output->HasLogs(); }
/** Returns whether the output has any errors. */
inline bool HasError() const { return Output->HasError(); }
/** Saves the build output to a compact binary object with values as attachments. */
void Save(FCbWriter& Writer) const
{
Output->Save(Writer);
}
/** Saves the build output to a cache record. */
void Save(FCacheRecordBuilder& RecordBuilder) const
{
Output->Save(RecordBuilder);
}
/**
* Load a build output.
*
* @param Name The name by which to identify this output for logging and profiling.
* @param Function The name of the build function that produced this output.
* @param Output The saved output to load.
* @return A valid build output, or null on error.
*/
UE_API static FOptionalBuildOutput Load(const FSharedString& Name, const FUtf8SharedString& Function, const FCbObject& Output);
UE_API static FOptionalBuildOutput Load(const FSharedString& Name, const FUtf8SharedString& Function, const FCacheRecord& Output);
private:
friend class FOptionalBuildOutput;
friend FBuildOutput Private::CreateBuildOutput(Private::IBuildOutputInternal* Output);
inline explicit FBuildOutput(Private::IBuildOutputInternal* InOutput)
: Output(InOutput)
{
}
TRefCountPtr<Private::IBuildOutputInternal> Output;
};
/**
* A build output builder is used to construct a build output.
*
* Create using IBuild::CreateOutput().
*
* @see FBuildOutput
*/
class FBuildOutputBuilder
{
public:
/** Add metadata to the output. The key must be unique in this output. */
inline void AddMeta(FUtf8StringView Key, const FCbField& Meta)
{
return OutputBuilder->AddMeta(Key, Meta);
}
/** Add a value to the output. The ID must be unique in this output. */
inline void AddValue(const FValueId& Id, const FValue& Value)
{
OutputBuilder->AddValue(Id, Value);
}
/** Add a message to the output. */
inline void AddMessage(const FBuildOutputMessage& Message)
{
OutputBuilder->AddMessage(Message);
}
/** Add a log to the output. */
inline void AddLog(const FBuildOutputLog& Log)
{
OutputBuilder->AddLog(Log);
}
/** Returns whether the output has any errors. */
inline bool HasError() const
{
return OutputBuilder->HasError();
}
/** Build a build output, which makes this builder subsequently unusable. */
inline FBuildOutput Build()
{
ON_SCOPE_EXIT { OutputBuilder = nullptr; };
return OutputBuilder->Build();
}
private:
friend FBuildOutputBuilder Private::CreateBuildOutputBuilder(Private::IBuildOutputBuilderInternal* OutputBuilder);
/** Construct a build output builder. Use IBuild::CreateOutput(). */
inline explicit FBuildOutputBuilder(Private::IBuildOutputBuilderInternal* InOutputBuilder)
: OutputBuilder(InOutputBuilder)
{
}
TUniquePtr<Private::IBuildOutputBuilderInternal> OutputBuilder;
};
/**
* A build output that can be null.
*
* @see FBuildOutput
*/
class FOptionalBuildOutput : private FBuildOutput
{
public:
inline FOptionalBuildOutput() : FBuildOutput(nullptr) {}
inline FOptionalBuildOutput(FBuildOutput&& InOutput) : FBuildOutput(MoveTemp(InOutput)) {}
inline FOptionalBuildOutput(const FBuildOutput& InOutput) : FBuildOutput(InOutput) {}
inline FOptionalBuildOutput& operator=(FBuildOutput&& InOutput) { FBuildOutput::operator=(MoveTemp(InOutput)); return *this; }
inline FOptionalBuildOutput& operator=(const FBuildOutput& InOutput) { FBuildOutput::operator=(InOutput); return *this; }
/** Returns the build output. The caller must check for null before using this accessor. */
inline const FBuildOutput& Get() const & { return *this; }
inline FBuildOutput Get() && { return MoveTemp(*this); }
inline bool IsNull() const { return !IsValid(); }
inline bool IsValid() const { return Output.IsValid(); }
inline explicit operator bool() const { return IsValid(); }
inline void Reset() { *this = FOptionalBuildOutput(); }
};
} // UE::DerivedData
#undef UE_API