You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
384 lines
17 KiB
C#
384 lines
17 KiB
C#
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
using EpicGames.Core;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UnrealBuildBase;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace UnrealBuildTool
|
|
{
|
|
/// <summary>
|
|
/// Common option flags for the Clang toolchains.
|
|
/// Usage of these flags is currently inconsistent between various toolchains.
|
|
/// </summary>
|
|
[Flags]
|
|
enum ClangToolChainOptions
|
|
{
|
|
/// <summary>
|
|
/// No custom options
|
|
/// </summary>
|
|
None = 0,
|
|
|
|
/// <summary>
|
|
/// Enable address sanitzier
|
|
/// </summary>
|
|
EnableAddressSanitizer = 1 << 0,
|
|
|
|
/// <summary>
|
|
/// Enable hardware address sanitzier
|
|
/// </summary>
|
|
EnableHWAddressSanitizer = 1 << 1,
|
|
|
|
/// <summary>
|
|
/// Enable thread sanitizer
|
|
/// </summary>
|
|
EnableThreadSanitizer = 1 << 2,
|
|
|
|
/// <summary>
|
|
/// Enable undefined behavior sanitizer
|
|
/// </summary>
|
|
EnableUndefinedBehaviorSanitizer = 1 << 3,
|
|
|
|
/// <summary>
|
|
/// Enable minimal undefined behavior sanitizer
|
|
/// </summary>
|
|
EnableMinimalUndefinedBehaviorSanitizer = 1 << 4,
|
|
|
|
/// <summary>
|
|
/// Enable memory sanitizer
|
|
/// </summary>
|
|
EnableMemorySanitizer = 1 << 5,
|
|
|
|
/// <summary>
|
|
/// Enable Shared library for the Sanitizers otherwise defaults to Statically linked
|
|
/// </summary>
|
|
EnableSharedSanitizer = 1 << 6,
|
|
|
|
/// <summary>
|
|
/// Enables link time optimization (LTO). Link times will significantly increase.
|
|
/// </summary>
|
|
EnableLinkTimeOptimization = 1 << 7,
|
|
|
|
/// <summary>
|
|
/// Enable thin LTO
|
|
/// </summary>
|
|
EnableThinLTO = 1 << 8,
|
|
|
|
/// <summary>
|
|
/// If should disable using objcopy to split the debug info into its own file or now
|
|
/// When we support larger the 4GB files with objcopy.exe this can be removed!
|
|
/// </summary>
|
|
DisableSplitDebugInfoWithObjCopy = 1 << 9,
|
|
|
|
/// <summary>
|
|
/// Enable tuning of debug info for LLDB
|
|
/// </summary>
|
|
TuneDebugInfoForLLDB = 1 << 10,
|
|
|
|
/// <summary>
|
|
/// Whether or not to preserve the portable symbol file produced by dump_syms
|
|
/// </summary>
|
|
PreservePSYM = 1 << 11,
|
|
|
|
/// <summary>
|
|
/// (Apple toolchains) Whether we're outputting a dylib instead of an executable
|
|
/// </summary>
|
|
OutputDylib = 1 << 12,
|
|
|
|
/// <summary>
|
|
/// Enables the creation of custom symbol files used for runtime symbol resolution.
|
|
/// </summary>
|
|
GenerateSymbols = 1 << 13,
|
|
|
|
/// <summary>
|
|
/// Enables live code editing
|
|
/// </summary>
|
|
EnableLiveCodeEditing = 1 << 14,
|
|
|
|
/// <summary>
|
|
/// Enables dead code/data stripping and common code folding.
|
|
/// </summary>
|
|
EnableDeadStripping = 1 << 15
|
|
}
|
|
|
|
abstract class ClangToolChain : ISPCToolChain
|
|
{
|
|
// The Clang version being used to compile
|
|
protected string? ClangVersionString = null;
|
|
protected int ClangVersionMajor = -1;
|
|
protected int ClangVersionMinor = -1;
|
|
protected int ClangVersionPatch = -1;
|
|
|
|
protected ClangToolChainOptions Options;
|
|
|
|
public ClangToolChain(ClangToolChainOptions InOptions, ILogger InLogger)
|
|
: base(InLogger)
|
|
{
|
|
Options = InOptions;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sanitizes a preprocessor definition argument if needed.
|
|
/// </summary>
|
|
/// <param name="Definition">A string in the format "foo=bar" or "foo".</param>
|
|
/// <returns>An escaped string</returns>
|
|
protected virtual string EscapePreprocessorDefinition(string Definition)
|
|
{
|
|
// By default don't modify preprocessor definition, handle in platform overrides.
|
|
return Definition;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks if compiler version matches the requirements
|
|
/// </summary>
|
|
protected bool CompilerVersionGreaterOrEqual(int Major, int Minor, int Patch)
|
|
{
|
|
// TODO: Temporary verification check to ensure a clang version has been set until ClangVersion is standarized across all clang-based toolchains.
|
|
if (ClangVersionMajor == -1 || ClangVersionMinor == -1 || ClangVersionPatch == -1)
|
|
{
|
|
throw new BuildException($"ClangVersion not valid ({ClangVersionMajor}.{ClangVersionMinor}.{ClangVersionPatch}), unable to check compiler version requirements");
|
|
}
|
|
|
|
return new Version(ClangVersionMajor, ClangVersionMinor, ClangVersionPatch) >= new Version(Major, Minor, Patch);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks if compiler version matches the requirements
|
|
/// </summary>
|
|
protected bool CompilerVersionLessThan(int Major, int Minor, int Patch)
|
|
{
|
|
// TODO: Temporary verification check until ClangVersion is standarized across all clang-based toolchains to ensure a version has been set.
|
|
if (ClangVersionMajor == -1 || ClangVersionMinor == -1 || ClangVersionPatch == -1)
|
|
{
|
|
throw new BuildException($"ClangVersion not valid ({ClangVersionMajor}.{ClangVersionMinor}.{ClangVersionPatch}), unable to check compiler version requirements");
|
|
}
|
|
|
|
return new Version(ClangVersionMajor, ClangVersionMinor, ClangVersionPatch) < new Version(Major, Minor, Patch);
|
|
}
|
|
|
|
protected virtual void GetCppStandardCompileArgument(CppCompileEnvironment CompileEnvironment, List<string> Arguments)
|
|
{
|
|
switch (CompileEnvironment.CppStandard)
|
|
{
|
|
case CppStandardVersion.Cpp14:
|
|
Arguments.Add("-std=c++14");
|
|
break;
|
|
case CppStandardVersion.Latest:
|
|
case CppStandardVersion.Cpp17:
|
|
Arguments.Add("-std=c++17");
|
|
break;
|
|
case CppStandardVersion.Cpp20:
|
|
Arguments.Add("-std=c++20");
|
|
break;
|
|
default:
|
|
throw new BuildException($"Unsupported C++ standard type set: {CompileEnvironment.CppStandard}");
|
|
}
|
|
|
|
if (CompileEnvironment.bEnableCoroutines)
|
|
{
|
|
Arguments.Add("-fcoroutines-ts");
|
|
if (!CompileEnvironment.bEnableExceptions)
|
|
{
|
|
Arguments.Add("-Wno-coroutine-missing-unhandled-exception");
|
|
}
|
|
}
|
|
}
|
|
|
|
protected virtual void GetCompileArguments_CPP(CppCompileEnvironment CompileEnvironment, List<string> Arguments)
|
|
{
|
|
Arguments.Add("-x c++");
|
|
GetCppStandardCompileArgument(CompileEnvironment, Arguments);
|
|
}
|
|
|
|
protected virtual void GetCompileArguments_C(CppCompileEnvironment CompileEnvironment, List<string> Arguments)
|
|
{
|
|
Arguments.Add("-x c");
|
|
}
|
|
|
|
protected virtual void GetCompileArguments_MM(CppCompileEnvironment CompileEnvironment, List<string> Arguments)
|
|
{
|
|
Arguments.Add("-x objective-c++");
|
|
Arguments.Add("-fobjc-abi-version=2");
|
|
Arguments.Add("-fobjc-legacy-dispatch");
|
|
GetCppStandardCompileArgument(CompileEnvironment, Arguments);
|
|
}
|
|
|
|
protected virtual void GetCompileArguments_M(CppCompileEnvironment CompileEnvironment, List<string> Arguments)
|
|
{
|
|
Arguments.Add("-x objective-c");
|
|
Arguments.Add("-fobjc-abi-version=2");
|
|
Arguments.Add("-fobjc-legacy-dispatch");
|
|
GetCppStandardCompileArgument(CompileEnvironment, Arguments);
|
|
}
|
|
|
|
protected virtual void GetCompileArguments_PCH(CppCompileEnvironment CompileEnvironment, List<string> Arguments)
|
|
{
|
|
Arguments.Add("-x c++-header");
|
|
if (CompilerVersionGreaterOrEqual(11, 0, 0))
|
|
{
|
|
Arguments.Add("-fpch-validate-input-files-content");
|
|
Arguments.Add("-fpch-instantiate-templates");
|
|
}
|
|
GetCppStandardCompileArgument(CompileEnvironment, Arguments);
|
|
}
|
|
|
|
// Conditionally enable (default disabled) generation of information about every class with virtual functions for use by the C++ runtime type identification features
|
|
// (`dynamic_cast' and `typeid'). If you don't use those parts of the language, you can save some space by using -fno-rtti.
|
|
// Note that exception handling uses the same information, but it will generate it as needed.
|
|
protected virtual string GetRTTIFlag(CppCompileEnvironment CompileEnvironment)
|
|
{
|
|
return CompileEnvironment.bUseRTTI ? "-frtti" : "-fno-rtti";
|
|
}
|
|
|
|
protected virtual string GetUserIncludePathArgument(DirectoryReference IncludePath)
|
|
{
|
|
return $"-I\"{NormalizeCommandLinePath(IncludePath)}\"";
|
|
}
|
|
|
|
protected virtual string GetSystemIncludePathArgument(DirectoryReference IncludePath)
|
|
{
|
|
// TODO: System include paths can be included with -isystem
|
|
return $"-I\"{NormalizeCommandLinePath(IncludePath)}\"";
|
|
}
|
|
|
|
protected virtual void GetCompileArguments_IncludePaths(CppCompileEnvironment CompileEnvironment, List<string> Arguments)
|
|
{
|
|
Arguments.AddRange(CompileEnvironment.UserIncludePaths.Select(IncludePath => GetUserIncludePathArgument(IncludePath)));
|
|
Arguments.AddRange(CompileEnvironment.SystemIncludePaths.Select(IncludePath => GetSystemIncludePathArgument(IncludePath)));
|
|
}
|
|
|
|
protected virtual string GetPreprocessorDefinitionArgument(string Definition)
|
|
{
|
|
return $"-D\"{EscapePreprocessorDefinition(Definition)}\"";
|
|
}
|
|
|
|
protected virtual void GetCompileArguments_PreprocessorDefinitions(CppCompileEnvironment CompileEnvironment, List<string> Arguments)
|
|
{
|
|
Arguments.AddRange(CompileEnvironment.Definitions.Select(Definition => GetPreprocessorDefinitionArgument(Definition)));
|
|
}
|
|
|
|
protected virtual string GetForceIncludeFileArgument(FileReference ForceIncludeFile)
|
|
{
|
|
return $"-include \"{NormalizeCommandLinePath(ForceIncludeFile)}\"";
|
|
}
|
|
|
|
protected virtual string GetForceIncludeFileArgument(FileItem ForceIncludeFile)
|
|
{
|
|
return GetForceIncludeFileArgument(ForceIncludeFile.Location);
|
|
}
|
|
|
|
protected virtual void GetCompileArguments_ForceInclude(CppCompileEnvironment CompileEnvironment, List<string> Arguments)
|
|
{
|
|
Arguments.AddRange(CompileEnvironment.ForceIncludeFiles.Select(ForceIncludeFile => GetForceIncludeFileArgument(ForceIncludeFile)));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Common compile arguments that control which warnings are enabled.
|
|
/// https://clang.llvm.org/docs/DiagnosticsReference.html
|
|
/// </summary>
|
|
/// <param name="CompileEnvironment"></param>
|
|
/// <param name="Arguments"></param>
|
|
protected virtual void GetCompileArguments_WarningsAndErrors(CppCompileEnvironment CompileEnvironment, List<string> Arguments)
|
|
{
|
|
Arguments.Add("-Wall"); // https://clang.llvm.org/docs/DiagnosticsReference.html#wall
|
|
Arguments.Add("-Werror"); // https://clang.llvm.org/docs/UsersManual.html#cmdoption-werror
|
|
|
|
Arguments.Add("-Wdelete-non-virtual-dtor"); // https://clang.llvm.org/docs/DiagnosticsReference.html#wdelete-non-virtual-dtor
|
|
Arguments.Add("-Wenum-conversion"); // https://clang.llvm.org/docs/DiagnosticsReference.html#wenum-conversion
|
|
Arguments.Add("-Wbitfield-enum-conversion"); // https://clang.llvm.org/docs/DiagnosticsReference.html#wbitfield-enum-conversion
|
|
|
|
Arguments.Add("-Wno-enum-enum-conversion"); // https://clang.llvm.org/docs/DiagnosticsReference.html#wenum-enum-conversion // ?? no reason given
|
|
Arguments.Add("-Wno-enum-float-conversion"); // https://clang.llvm.org/docs/DiagnosticsReference.html#wenum-float-conversion // ?? no reason given
|
|
|
|
if (CompilerVersionGreaterOrEqual(13, 0, 0))
|
|
{
|
|
Arguments.Add("-Wno-unused-but-set-variable"); // https://clang.llvm.org/docs/DiagnosticsReference.html#wunused-but-set-variable // new warning for clang 13
|
|
Arguments.Add("-Wno-unused-but-set-parameter"); // https://clang.llvm.org/docs/DiagnosticsReference.html#wunused-but-set-parameter // new warning for clang 13
|
|
Arguments.Add("-Wno-ordered-compare-function-pointers"); // https://clang.llvm.org/docs/DiagnosticsReference.html#wordered-compare-function-pointers // new warning for clang 13
|
|
}
|
|
|
|
Arguments.Add("-Wno-gnu-string-literal-operator-template"); // https://clang.llvm.org/docs/DiagnosticsReference.html#wgnu-string-literal-operator-template // We use this feature to allow static FNames.
|
|
Arguments.Add("-Wno-inconsistent-missing-override"); // https://clang.llvm.org/docs/DiagnosticsReference.html#winconsistent-missing-override // ?? no reason given
|
|
Arguments.Add("-Wno-invalid-offsetof"); // https://clang.llvm.org/docs/DiagnosticsReference.html#winvalid-offsetof // needed to suppress warnings about using offsetof on non-POD types.
|
|
Arguments.Add("-Wno-switch"); // https://clang.llvm.org/docs/DiagnosticsReference.html#wswitch // this hides the "enumeration value 'XXXXX' not handled in switch [-Wswitch]" warnings - we should maybe remove this at some point and add UE_LOG(, Fatal, ) to default cases
|
|
Arguments.Add("-Wno-tautological-compare"); // https://clang.llvm.org/docs/DiagnosticsReference.html#wtautological-compare // this hides the "warning : comparison of unsigned expression < 0 is always false" type warnings due to constant comparisons, which are possible with template arguments
|
|
Arguments.Add("-Wno-unknown-pragmas"); // https://clang.llvm.org/docs/DiagnosticsReference.html#wunknown-pragmas // Slate triggers this (with its optimize on/off pragmas)
|
|
Arguments.Add("-Wno-unused-function"); // https://clang.llvm.org/docs/DiagnosticsReference.html#wunused-function // this will hide the warnings about static functions in headers that aren't used in every single .cpp file
|
|
Arguments.Add("-Wno-unused-lambda-capture"); // https://clang.llvm.org/docs/DiagnosticsReference.html#wunused-lambda-capture // suppressed because capturing of compile-time constants is seemingly inconsistent. And MSVC doesn't do that.
|
|
Arguments.Add("-Wno-unused-local-typedef"); // https://clang.llvm.org/docs/DiagnosticsReference.html#wunused-local-typedef // clang is being overly strict here? PhysX headers trigger this.
|
|
Arguments.Add("-Wno-unused-private-field"); // https://clang.llvm.org/docs/DiagnosticsReference.html#wunused-private-field // this will prevent the issue of warnings for unused private variables. MultichannelTcpSocket.h triggers this, possibly more
|
|
Arguments.Add("-Wno-unused-variable"); // https://clang.llvm.org/docs/DiagnosticsReference.html#wunused-variable // ?? no reason given
|
|
Arguments.Add("-Wno-undefined-var-template"); // https://clang.llvm.org/docs/DiagnosticsReference.html#wundefined-var-template // not really a good warning to disable
|
|
|
|
// Profile Guided Optimization (PGO) and Link Time Optimization (LTO)
|
|
if (CompileEnvironment.bPGOOptimize)
|
|
{
|
|
//
|
|
// Clang emits warnings for each compiled object file that doesn't have a matching entry in the profile data.
|
|
// This can happen when the profile data is older than the binaries we're compiling.
|
|
//
|
|
// Disable these warnings. They are far too verbose.
|
|
//
|
|
Arguments.Add("-Wno-profile-instr-out-of-date"); // https://clang.llvm.org/docs/DiagnosticsReference.html#wprofile-instr-out-of-date
|
|
Arguments.Add("-Wno-profile-instr-unprofiled"); // https://clang.llvm.org/docs/DiagnosticsReference.html#wprofile-instr-unprofiled
|
|
|
|
// apparently there can be hashing conflicts with PGO which can result in:
|
|
// 'Function control flow change detected (hash mismatch)' warnings.
|
|
Arguments.Add("-Wno-backend-plugin"); // https://clang.llvm.org/docs/DiagnosticsReference.html#wbackend-plugin
|
|
}
|
|
|
|
// shipping builds will cause this warning with "ensure", so disable only in those case
|
|
if (CompileEnvironment.Configuration == CppConfiguration.Shipping)
|
|
{
|
|
Arguments.Add("-Wno-unused-value"); // https://clang.llvm.org/docs/DiagnosticsReference.html#wunused-value
|
|
}
|
|
|
|
// https://clang.llvm.org/docs/DiagnosticsReference.html#wdeprecated-declarations
|
|
if (CompileEnvironment.DeprecationWarningLevel == WarningLevel.Error)
|
|
{
|
|
// TODO: This may be unnecessary with -Werror
|
|
Arguments.Add("-Werror=deprecated-declarations");
|
|
}
|
|
|
|
// https://clang.llvm.org/docs/DiagnosticsReference.html#wshadow
|
|
if (CompileEnvironment.ShadowVariableWarningLevel != WarningLevel.Off)
|
|
{
|
|
Arguments.Add("-Wshadow" + ((CompileEnvironment.ShadowVariableWarningLevel == WarningLevel.Error) ? "" : " -Wno-error=shadow"));
|
|
}
|
|
|
|
// https://clang.llvm.org/docs/DiagnosticsReference.html#wundef
|
|
if (CompileEnvironment.bEnableUndefinedIdentifierWarnings)
|
|
{
|
|
Arguments.Add("-Wundef" + (CompileEnvironment.bUndefinedIdentifierWarningsAsErrors ? "" : " -Wno-error=undef"));
|
|
}
|
|
|
|
// always use absolute paths for errors, this can help IDEs go to the error properly
|
|
Arguments.Add("-fdiagnostics-absolute-paths");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Common compile arguments for all files in a module.
|
|
/// Override and call base.GetCompileArguments_Global() in derived classes.
|
|
/// </summary>
|
|
///
|
|
/// <param name="CompileEnvironment"></param>
|
|
/// <param name="Arguments"></param>
|
|
protected virtual void GetCompileArguments_Global(CppCompileEnvironment CompileEnvironment, List<string> Arguments)
|
|
{
|
|
// build up the commandline common to C and C++
|
|
Arguments.Add("-c");
|
|
Arguments.Add("-pipe");
|
|
|
|
// Add include paths to the argument list.
|
|
GetCompileArguments_IncludePaths(CompileEnvironment, Arguments);
|
|
|
|
// Add preprocessor definitions to the argument list.
|
|
GetCompileArguments_PreprocessorDefinitions(CompileEnvironment, Arguments);
|
|
|
|
// Add warning and error flags to the argument list.
|
|
GetCompileArguments_WarningsAndErrors(CompileEnvironment, Arguments);
|
|
}
|
|
}
|
|
} |