// Copyright Epic Games, Inc. All Rights Reserved.
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using EpicGames.Core;
using Microsoft.Extensions.Logging;
using OpenTracing.Util;
using static UnrealBuildTool.DataDrivenPlatformInfo;
namespace UnrealBuildTool
{
///
/// Enum for the different ways a platform can support multiple architectures within UnrealBuildTool
///
public enum UnrealArchitectureMode
{
///
/// This platform only supports a single architecture (consoles, etc)
///
SingleArchitecture,
///
/// This platform needs separate targets per architecture (compiling for multiple will compile two entirely separate set of source/exectuable/intermediates)
///
OneTargetPerArchitecture,
///
/// This will create a single target, but compile each source file separately
///
SingleTargetCompileSeparately,
///
/// This will create a single target, but compile each source file and link the executable separately - but then packaged together into one final output
///
SingleTargetLinkSeparately,
}
///
/// Full architecture configuation information for a platform. Can be found by platform with UnrealArchitectureConfig.ForPlatform(), or UEBuildPlatform.ArchitectureConfig
///
public class UnrealArchitectureConfig
{
///
/// Get the architecture configuration object for a given platform
///
///
///
public static UnrealArchitectureConfig ForPlatform(UnrealTargetPlatform Platform)
{
return UEBuildPlatform.GetBuildPlatform(Platform).ArchitectureConfig;
}
///
/// Get all known ArchitectureConfig objects
///
///
public static IEnumerable AllConfigs()
{
// return ArchConfigs for platforms that have a BuildPlatform (which is where the Configs are stored)
return UnrealTargetPlatform.GetValidPlatforms().Where(x => UEBuildPlatform.TryGetBuildPlatform(x, out _)).Select(x => UEBuildPlatform.GetBuildPlatform(x).ArchitectureConfig);
}
///
/// The multi-architecture mode for this platform (potentially single-architecture)
///
public UnrealArchitectureMode Mode { get; }
///
/// The set of all architecture this platform supports. Any platform specified on the UBT commandline not in this list will be an error
///
public UnrealArchitectures AllSupportedArchitectures { get; }
///
/// This determines what architecture(s) to compile/package when no architeecture is specified on the commandline
///
///
///
///
public virtual UnrealArchitectures ActiveArchitectures(FileReference? ProjectFile, string? TargetName)
{
if (Mode != UnrealArchitectureMode.SingleArchitecture || AllSupportedArchitectures.bIsMultiArch)
{
throw new BuildException("Platforms that support multiple platforms are expected to override ActiveArchitectures in a platform-specifiec UnraelArchitectureConfig subclass");
}
return AllSupportedArchitectures;
}
///
/// Like ProjectSupportedArchitectures, except when building in distribution mode. Defaults to ActiveArchitectures
///
///
///
///
public virtual UnrealArchitectures DistributionArchitectures(FileReference? ProjectFile, string? TargetName)
{
return ActiveArchitectures(ProjectFile, TargetName);
}
///
/// Returns the set all architectures potentially supported by this project. Can be used by project file gnenerators to restrict IDE architecture options
/// Defaults to AllSupportedArchitectures
///
///
///
///
public virtual UnrealArchitectures ProjectSupportedArchitectures(FileReference? ProjectFile, string? TargetName)
{
return AllSupportedArchitectures;
}
///
/// Returns if architecture name should be used when making intermediate directories, per-architecture filenames, etc
/// It is virtual, so a platform can choose to skip architecture name for one platform, but not another
///
///
public virtual bool RequiresArchitectureFilenames(UnrealArchitectures Architectures)
{
// @todo: this needs to also have directory vs file (we may need directory names but not filenames in the case of Single-target multi-arch)
return Mode == UnrealArchitectureMode.OneTargetPerArchitecture;
}
///
/// Convert user specified architecture strings to what the platform wants
///
///
///
public virtual string ConvertToReadableArchitecture(UnrealArch Architecture)
{
return Architecture.ToString();
}
///
/// Get name for architecture-specific directories (can be shorter than architecture name itself)
///
public virtual string GetFolderNameForArchitecture(UnrealArch Architecture)
{
// by default, use the architecture name
return Architecture.ToString();
}
///
/// Get name for architecture-specific directories (can be shorter than architecture name itself)
///
public virtual string GetFolderNameForArchitectures(UnrealArchitectures Architectures)
{
// by default, use the architecture names combined with +
return Architectures.GetFolderNameForPlatform(this);
}
///
/// Returns the architecture of the currently running OS (only used for desktop platforms, so will throw an exception in the general case)
///
///
public virtual UnrealArch GetHostArchitecture()
{
if (AllSupportedArchitectures.bIsMultiArch)
{
throw new BuildException($"Asking for Host architecture from {GetType()} which supports multiple architectures, but did not override GetHostArchitecture()");
}
return AllSupportedArchitectures.SingleArchitecture;
}
///
/// Simple constructor for platforms with a single architecture
///
///
public UnrealArchitectureConfig(UnrealArch SingleArchitecture)
{
Mode = UnrealArchitectureMode.SingleArchitecture;
AllSupportedArchitectures = new UnrealArchitectures(SingleArchitecture);
}
///
/// Full constructor for platforms that support multiple architectures
///
///
///
protected UnrealArchitectureConfig(UnrealArchitectureMode Mode, IEnumerable SupportedArchitectures)
{
this.Mode = Mode;
AllSupportedArchitectures = new UnrealArchitectures(SupportedArchitectures);
}
}
abstract class UEBuildPlatform
{
private static Dictionary BuildPlatformDictionary = new Dictionary();
// a mapping of a group to the platforms in the group (ie, Microsoft contains Win32 and Win64)
static Dictionary> PlatformGroupDictionary = new Dictionary>();
///
/// The corresponding target platform enum
///
public readonly UnrealTargetPlatform Platform;
///
/// The configuration about the architecture(s) this platform supports
///
public readonly UnrealArchitectureConfig ArchitectureConfig;
///
/// Logger for this platform
///
protected readonly ILogger Logger;
///
/// All the platform folder names
///
private static string[]? CachedPlatformFolderNames;
///
/// Cached copy of the list of folders to include for this platform
///
private IReadOnlySet? CachedIncludedFolderNames;
///
/// Cached copy of the list of folders to exclude for this platform
///
private IReadOnlySet? CachedExcludedFolderNames;
///
/// Constructor.
///
/// The enum value for this platform
/// The SDK management object for this platform
/// THe architecture configuraton for this platform. This is returned by UnrealArchitectureConfig.ForPlatform()
/// Logger for output
public UEBuildPlatform(UnrealTargetPlatform InPlatform, UEBuildPlatformSDK SDK, UnrealArchitectureConfig ArchitectureConfig, ILogger InLogger)
{
Platform = InPlatform;
Logger = InLogger;
this.ArchitectureConfig = ArchitectureConfig;
// check DDPI to see if the platform is enabled on this host platform
string IniPlatformName = ConfigHierarchy.GetIniPlatformName(Platform);
bool bIsEnabled = false;
ConfigDataDrivenPlatformInfo? DDPI = DataDrivenPlatformInfo.GetDataDrivenInfoForPlatform(IniPlatformName);
if (DDPI != null)
{
bIsEnabled = DDPI.bIsEnabled;
}
// set up the SDK if the platform is enabled
UEBuildPlatformSDK.RegisterSDKForPlatform(SDK, Platform.ToString(), bIsEnabled);
if (bIsEnabled)
{
SDK.ManageAndValidateSDK();
}
}
private static string[] UATProjectParams = { "-project=", "-scriptsforproject=" };
private static void InitializePerPlatformSDKs(string[] Args, bool bArgumentsAreForUBT, ILogger Logger)
{
// Before we setup AutoSDK, we check to see if any projects need to override the Main version so that AutoSDK
// will set up an alternate SDK
Dictionary PlatformToVersionMap = new();
IEnumerable ProjectFiles;
if (bArgumentsAreForUBT == false)
{
ProjectFiles = Args
// find arguments that start with one of the hard-coded parameters
.Where(x => UATProjectParams.Any(y => x.StartsWith(y, StringComparison.OrdinalIgnoreCase)))
// treat the part after the = as a path to a uproject, and ask the NativeProjects class to find a .uproject
.Select(x => NativeProjects.FindProjectFile(x.Substring(x.IndexOf('=') + 1), Logger))
// only use existant projects
.Where(x => x != null && FileReference.Exists(x));
}
else
{
CommandLineArguments CommandLine = new(Args);
BuildConfiguration BuildConfiguration = new();
XmlConfig.ApplyTo(BuildConfiguration);
CommandLine.ApplyTo(BuildConfiguration);
// get the project files for all targets - we allow null uproject files which means to use the defaults
// (same as a uproject that has no override SDK versions set)
ProjectFiles = TargetDescriptor.ParseCommandLineForProjects(CommandLine, Logger);
}
UEBuildPlatformSDK.InitializePerProjectSDKVersions(ProjectFiles.OfType());
// clear the cache used for auto-switching to the best manually-installed SDK
UEBuildPlatformSDK.ClearManualSDKEnvVarCache();
}
///
/// Finds all the UEBuildPlatformFactory types in this assembly and uses them to register all the available platforms, and uses a UBT commandline to check for per-project SDKs
///
/// Whether to register platforms that are not installed
/// Only register the host platform
/// Commandline args to look through for finding uprojects, to look up per-project SDK versions
/// The UBT mode (usually Build, but
/// Logger for output
internal static void RegisterPlatforms(bool bIncludeNonInstalledPlatforms, bool bHostPlatformOnly, Type UBTModeType, string[] ArgumentsForPerPlatform, ILogger Logger)
{
bool bUseTargetTripleParams = false;
// @todo : add a ToolModeOptions.UseTargetTripleCommandLine or something
if (UBTModeType.Name == "BuildMode")
{
bUseTargetTripleParams = true;
}
RegisterPlatforms(bIncludeNonInstalledPlatforms, bHostPlatformOnly, ArgumentsForPerPlatform, bArgumentsAreForUBT: bUseTargetTripleParams, Logger);
}
///
/// Finds all the UEBuildPlatformFactory types in this assembly and uses them to register all the available platforms, and uses a UAT commandline to check for per-project SDKs
///
/// Whether to register platforms that are not installed
/// Only register the host platform
/// Commandline args to look through for finding uprojects, to look up per-project SDK versions
/// Logger for output
internal static void RegisterPlatforms(bool bIncludeNonInstalledPlatforms, bool bHostPlatformOnly, string[] ArgumentsForPerPlatform, ILogger Logger)
{
RegisterPlatforms(bIncludeNonInstalledPlatforms, bHostPlatformOnly, ArgumentsForPerPlatform, bArgumentsAreForUBT: false, Logger);
}
private static void RegisterPlatforms(bool bIncludeNonInstalledPlatforms, bool bHostPlatformOnly, string[] ArgumentsForPerPlatform, bool bArgumentsAreForUBT, ILogger Logger)
{
// Initialize the installed platform info
using (GlobalTracer.Instance.BuildSpan("Initializing InstalledPlatformInfo").StartActive())
{
InstalledPlatformInfo.Initialize();
}
using (GlobalTracer.Instance.BuildSpan("Initializing PerPlatformSDKs").StartActive())
{
InitializePerPlatformSDKs(ArgumentsForPerPlatform, bArgumentsAreForUBT, Logger);
}
// Find and register all tool chains and build platforms that are present
Type[] AllTypes;
using (GlobalTracer.Instance.BuildSpan("Querying types").StartActive())
{
AllTypes = Assembly.GetExecutingAssembly().GetTypes();
}
// register all build platforms first, since they implement SDK-switching logic that can set environment variables
foreach (Type CheckType in AllTypes)
{
if (CheckType.IsClass && !CheckType.IsAbstract)
{
if (CheckType.IsSubclassOf(typeof(UEBuildPlatformFactory)))
{
Logger.LogDebug(" Registering build platform: {Platform}", CheckType.ToString());
using (GlobalTracer.Instance.BuildSpan(CheckType.Name).StartActive())
{
UEBuildPlatformFactory TempInst = (UEBuildPlatformFactory)Activator.CreateInstance(CheckType)!;
if (bHostPlatformOnly && TempInst.TargetPlatform != BuildHostPlatform.Current.Platform)
{
continue;
}
// We need all platforms to be registered when we run -validateplatform command to check SDK status of each
if (bIncludeNonInstalledPlatforms || InstalledPlatformInfo.IsValidPlatform(TempInst.TargetPlatform))
{
TempInst.RegisterBuildPlatforms(Logger);
}
}
}
}
}
}
///
/// Gets an array of all platform folder names
///
/// Array of platform folders
public static string[] GetPlatformFolderNames()
{
if (CachedPlatformFolderNames == null)
{
List PlatformFolderNames = new List();
// Find all the platform folders to exclude from the list of precompiled modules
PlatformFolderNames.AddRange(UnrealTargetPlatform.GetValidPlatformNames());
// Also exclude all the platform groups that this platform is not a part of
PlatformFolderNames.AddRange(UnrealPlatformGroup.GetValidGroupNames());
// Save off the list as an array
CachedPlatformFolderNames = PlatformFolderNames.ToArray();
}
return CachedPlatformFolderNames;
}
///
/// Finds a list of folder names to include when building for this platform
///
public IReadOnlySet GetIncludedFolderNames()
{
if (CachedIncludedFolderNames == null)
{
HashSet Names = new HashSet(DirectoryReference.Comparer);
Names.Add(Platform.ToString());
foreach (UnrealPlatformGroup Group in UEBuildPlatform.GetPlatformGroups(Platform))
{
Names.Add(Group.ToString());
}
CachedIncludedFolderNames = Names;
}
return CachedIncludedFolderNames;
}
///
/// Finds a list of folder names to exclude when building for this platform
///
public IReadOnlySet GetExcludedFolderNames()
{
CachedExcludedFolderNames ??= new HashSet(GetPlatformFolderNames().Except(GetIncludedFolderNames()), DirectoryReference.Comparer);
return CachedExcludedFolderNames;
}
///
/// Whether the required external SDKs are installed for this platform. Could be either a manual install or an AutoSDK.
///
public SDKStatus HasRequiredSDKsInstalled()
{
UEBuildPlatformSDK? SDK = UEBuildPlatform.GetSDK(Platform);
if (SDK == null || !SDK.bIsSdkAllowedOnHost)
{
return SDKStatus.Invalid;
}
return SDK.HasRequiredSDKsInstalled();
}
///
/// Whether this platform requires specific Visual Studio version.
///
public virtual VCProjectFileFormat GetRequiredVisualStudioVersion()
{
return VCProjectFileFormat.Default;
}
///
/// The version required to support Visual Studio
///
public virtual Version GetVersionRequiredForVisualStudio(VCProjectFileFormat Format)
{
return new Version();
}
///
/// Gets all the registered platforms
///
/// Sequence of registered platforms
public static IEnumerable GetRegisteredPlatforms()
{
return BuildPlatformDictionary.Keys;
}
///
/// Searches a directory tree for build products to be cleaned.
///
/// The directory to search
/// Target or application names that may appear at the start of the build product name (eg. "UnrealEditor", "ShooterGameEditor")
/// Suffixes which may appear at the end of the build product name
/// List to receive a list of files to be cleaned
/// List to receive a list of directories to be cleaned
public void FindBuildProductsToClean(DirectoryReference BaseDir, string[] NamePrefixes, string[] NameSuffixes, List FilesToClean, List DirectoriesToClean)
{
foreach (FileReference File in DirectoryReference.EnumerateFiles(BaseDir))
{
string FileName = File.GetFileName();
if (IsDefaultBuildProduct(FileName, NamePrefixes, NameSuffixes) || IsBuildProduct(FileName, NamePrefixes, NameSuffixes))
{
FilesToClean.Add(File);
}
}
foreach (DirectoryReference SubDir in DirectoryReference.EnumerateDirectories(BaseDir))
{
string SubDirName = SubDir.GetDirectoryName();
if (IsBuildProduct(SubDirName, NamePrefixes, NameSuffixes))
{
DirectoriesToClean.Add(SubDir);
}
else
{
FindBuildProductsToClean(SubDir, NamePrefixes, NameSuffixes, FilesToClean, DirectoriesToClean);
}
}
}
///
/// Enumerates any additional directories needed to clean this target
///
/// The target to clean
/// Receives a list of files to be removed
/// Receives a list of directories to be removed
public virtual void FindAdditionalBuildProductsToClean(ReadOnlyTargetRules Target, List FilesToDelete, List DirectoriesToDelete)
{
}
///
/// Determines if a filename is a default UBT build product
///
/// The name to check
/// Target or application names that may appear at the start of the build product name (eg. "UnrealEditor", "ShooterGameEditor")
/// Suffixes which may appear at the end of the build product name
/// True if the substring matches the name of a build product, false otherwise
public static bool IsDefaultBuildProduct(string FileName, string[] NamePrefixes, string[] NameSuffixes)
{
return UEBuildPlatform.IsBuildProductName(FileName, NamePrefixes, NameSuffixes, ".target")
|| UEBuildPlatform.IsBuildProductName(FileName, NamePrefixes, NameSuffixes, ".modules")
|| UEBuildPlatform.IsBuildProductName(FileName, NamePrefixes, NameSuffixes, ".version");
}
///
/// Determines if the given name is a build product for a target.
///
/// The name to check
/// Target or application names that may appear at the start of the build product name (eg. "UnrealEditor", "ShooterGameEditor")
/// Suffixes which may appear at the end of the build product name
/// True if the string matches the name of a build product, false otherwise
public abstract bool IsBuildProduct(string FileName, string[] NamePrefixes, string[] NameSuffixes);
///
/// Determines if a string is in the canonical name of a UE build product, with a specific extension (eg. "UnrealEditor-Win64-Debug.exe" or "UnrealEditor-ModuleName-Win64-Debug.dll").
///
/// The file name to check
/// Target or application names that may appear at the start of the build product name (eg. "UnrealEditor", "ShooterGameEditor")
/// Suffixes which may appear at the end of the build product name
/// The extension to check for
/// True if the string matches the name of a build product, false otherwise
public static bool IsBuildProductName(string FileName, string[] NamePrefixes, string[] NameSuffixes, string Extension)
{
return IsBuildProductName(FileName, 0, FileName.Length, NamePrefixes, NameSuffixes, Extension);
}
///
/// Determines if a substring is in the canonical name of a UE build product, with a specific extension (eg. "UnrealEditor-Win64-Debug.exe" or "UnrealEditor-ModuleName-Win64-Debug.dll").
///
/// The name to check
/// Index of the first character to be checked
/// Number of characters of the substring to check
/// Target or application names that may appear at the start of the build product name (eg. "UnrealEditor", "ShooterGameEditor")
/// Suffixes which may appear at the end of the build product name
/// The extension to check for
/// True if the substring matches the name of a build product, false otherwise
public static bool IsBuildProductName(string FileName, int Index, int Count, string[] NamePrefixes, string[] NameSuffixes, string Extension)
{
// Check if the extension matches, and forward on to the next IsBuildProductName() overload without it if it does.
if (Count > Extension.Length && String.Compare(FileName, Index + Count - Extension.Length, Extension, 0, Extension.Length, StringComparison.InvariantCultureIgnoreCase) == 0)
{
return IsBuildProductName(FileName, Index, Count - Extension.Length, NamePrefixes, NameSuffixes);
}
return false;
}
///
/// Determines if a substring is in the canonical name of a UE build product, excluding extension or other decoration (eg. "UnrealEditor-Win64-Debug" or "UnrealEditor-ModuleName-Win64-Debug").
///
/// The name to check
/// Index of the first character to be checked
/// Number of characters of the substring to check
/// Target or application names that may appear at the start of the build product name (eg. "UnrealEditor", "ShooterGameEditor")
/// Suffixes which may appear at the end of the build product name
/// True if the substring matches the name of a build product, false otherwise
public static bool IsBuildProductName(string FileName, int Index, int Count, string[] NamePrefixes, string[] NameSuffixes)
{
foreach (string NamePrefix in NamePrefixes)
{
if (Count >= NamePrefix.Length && String.Compare(FileName, Index, NamePrefix, 0, NamePrefix.Length, StringComparison.InvariantCultureIgnoreCase) == 0)
{
int MinIdx = Index + NamePrefix.Length;
foreach (string NameSuffix in NameSuffixes)
{
int MaxIdx = Index + Count - NameSuffix.Length;
if (MaxIdx >= MinIdx && String.Compare(FileName, MaxIdx, NameSuffix, 0, NameSuffix.Length, StringComparison.InvariantCultureIgnoreCase) == 0)
{
if (MinIdx < MaxIdx && FileName[MinIdx] == '-')
{
MinIdx++;
while (MinIdx < MaxIdx && FileName[MinIdx] != '-' && FileName[MinIdx] != '.')
{
MinIdx++;
}
}
if (MinIdx == MaxIdx)
{
return true;
}
}
}
}
}
return false;
}
public virtual void PostBuildSync(UEBuildTarget Target)
{
}
///
/// Get the bundle directory for the shared link environment
///
/// The target rules
/// List of executable output files
/// Path to the bundle directory
public virtual DirectoryReference? GetBundleDirectory(ReadOnlyTargetRules Rules, List OutputFiles)
{
return null;
}
///
/// Determines whether a given platform is available
///
/// The platform to check for
/// Ignore the sdks presence when checking for platform availablity (many platforms can be cooked as a target platform without requiring sdk)
/// True if it's available, false otherwise
public static bool IsPlatformAvailable(UnrealTargetPlatform Platform, bool bIgnoreSDKCheck = false)
{
return BuildPlatformDictionary.ContainsKey(Platform) && (bIgnoreSDKCheck || BuildPlatformDictionary[Platform].HasRequiredSDKsInstalled() == SDKStatus.Valid);
}
///
/// Determines whether a given platform is available in the context of a particular Taget
///
/// The platform to check for
/// A Target object that may further restrict available platforms
/// Ignore the sdks presence when checking for platform availablity (many platforms can be cooked as a target platform without requiring sdk)
/// True if it's available, false otherwise
public static bool IsPlatformAvailableForTarget(UnrealTargetPlatform Platform, ReadOnlyTargetRules Target, bool bIgnoreSDKCheck = false)
{
return IsPlatformAvailable(Platform, bIgnoreSDKCheck) && Target.IsPlatformOptedIn(Platform);
}
///
/// Register the given platforms UEBuildPlatform instance
///
/// The UEBuildPlatform instance to use for the InPlatform
/// Logger for output
public static void RegisterBuildPlatform(UEBuildPlatform InBuildPlatform, ILogger Logger)
{
Logger.LogDebug(" Registering build platform: {Platform} - buildable: {Buildable}", InBuildPlatform.Platform, InBuildPlatform.HasRequiredSDKsInstalled() == SDKStatus.Valid);
if (BuildPlatformDictionary.ContainsKey(InBuildPlatform.Platform) == true)
{
Logger.LogWarning("RegisterBuildPlatform Warning: Registering build platform {Platform} for {ForPlatform} when it is already set to {CurPlatform}",
InBuildPlatform.ToString(), InBuildPlatform.Platform.ToString(), BuildPlatformDictionary[InBuildPlatform.Platform].ToString());
BuildPlatformDictionary[InBuildPlatform.Platform] = InBuildPlatform;
}
else
{
BuildPlatformDictionary.Add(InBuildPlatform.Platform, InBuildPlatform);
}
}
///
/// Assign a platform as a member of the given group
///
public static void RegisterPlatformWithGroup(UnrealTargetPlatform InPlatform, UnrealPlatformGroup InGroup)
{
// find or add the list of groups for this platform
List? Platforms;
if (!PlatformGroupDictionary.TryGetValue(InGroup, out Platforms))
{
Platforms = new List();
PlatformGroupDictionary.Add(InGroup, Platforms);
}
Platforms.Add(InPlatform);
}
///
/// Retrieve the list of platforms in this group (if any)
///
public static List GetPlatformsInGroup(UnrealPlatformGroup InGroup)
{
List? PlatformList;
if (!PlatformGroupDictionary.TryGetValue(InGroup, out PlatformList))
{
PlatformList = new List();
}
return PlatformList;
}
///
/// Enumerates all the platform groups for a given platform
///
/// The platform to look for
/// List of platform groups that this platform is a member of
public static IEnumerable GetPlatformGroups(UnrealTargetPlatform Platform)
{
return PlatformGroupDictionary.Where(x => x.Value.Contains(Platform)).Select(x => x.Key);
}
///
/// Retrieve the IUEBuildPlatform instance for the given TargetPlatform
///
/// The UnrealTargetPlatform being built
/// UEBuildPlatform The instance of the build platform
public static UEBuildPlatform GetBuildPlatform(UnrealTargetPlatform InPlatform)
{
UEBuildPlatform? Platform;
if (!TryGetBuildPlatform(InPlatform, out Platform))
{
throw new BuildException("GetBuildPlatform: No BuildPlatform found for {0}", InPlatform.ToString());
}
return Platform;
}
///
/// Retrieve the IUEBuildPlatform instance for the given TargetPlatform
///
/// The UnrealTargetPlatform being built
///
/// UEBuildPlatform The instance of the build platform
public static bool TryGetBuildPlatform(UnrealTargetPlatform InPlatform, [NotNullWhen(true)] out UEBuildPlatform? Platform)
{
return BuildPlatformDictionary.TryGetValue(InPlatform, out Platform);
}
///
/// Allow all registered build platforms to modify the newly created module
/// passed in for the given platform.
/// This is not required - but allows for hiding details of a particular platform.
///
/// The name of the module
/// The module rules
/// The target being build
public static void PlatformModifyHostModuleRules(string ModuleName, ModuleRules Rules, ReadOnlyTargetRules Target)
{
foreach (KeyValuePair PlatformEntry in BuildPlatformDictionary)
{
PlatformEntry.Value.ModifyModuleRulesForOtherPlatform(ModuleName, Rules, Target);
}
}
///
/// Returns the delimiter used to separate paths in the PATH environment variable for the platform we are executing on.
///
[Obsolete("Replace with System.IO.Path.PathSeparator")]
public static string GetPathVarDelimiter()
{
return Path.PathSeparator.ToString();
}
///
/// Gets the platform name that should be used.
///
public virtual string GetPlatformName()
{
return Platform.ToString();
}
///
/// If this platform can be compiled with XGE
///
public virtual bool CanUseXGE()
{
return true;
}
///
/// If this platform can be compiled with FASTBuild
///
public virtual bool CanUseFASTBuild()
{
return false;
}
///
/// If this platform can be compiled with SN-DBS
///
public virtual bool CanUseSNDBS()
{
return false;
}
///
/// Set all the platform-specific defaults for a new target
///
public virtual void ResetTarget(TargetRules Target)
{
}
///
/// Validate a target's settings
///
public virtual void ValidateTarget(TargetRules Target)
{
if (Target.bMergeModules)
{
ValidateMergedTarget(Target);
}
}
///
/// Validate a target's settings for merged modules
///
public virtual void ValidateMergedTarget(TargetRules Target)
{
}
///
/// Validate a plugin's settings
///
public virtual void ValidatePlugin(UEBuildPlugin Plugin, ReadOnlyTargetRules Target)
{
}
///
/// Validate a UEBuildModule before it's processed
/// The UEBuildModule that needs to be validated
/// Options for the target being built
/// The logger for output
///
public virtual void ValidateModule(UEBuildModule Module, ReadOnlyTargetRules Target, ILogger Logger)
{
}
///
/// Validate a UEBuildModule's include paths before it's processed
///
/// The UEBuildModule that needs to be validated
/// Options for the target being built
/// Other modules to validate against, if needed
/// The logger for output
public virtual bool ValidateModuleIncludePaths(UEBuildModule Module, ReadOnlyTargetRules Target, IEnumerable AllModules, ILogger Logger)
{
CppCompileWarnings ModuleWarningSettings = Module.Rules.CppCompileWarningSettings;
if (ModuleWarningSettings.ModuleIncludePathWarningLevel <= WarningLevel.Off
&& ModuleWarningSettings.ModuleIncludePrivateWarningLevel <= WarningLevel.Off
&& ModuleWarningSettings.ModuleIncludeSubdirectoryWarningLevel <= WarningLevel.Off)
{
return false;
}
bool AnyErrors = false;
void LoggerFunc(string? message, params object?[] args)
{
if (ModuleWarningSettings.ModuleIncludePathWarningLevel == WarningLevel.Warning)
{
Logger.LogWarning($"Warning: {message}", args);
}
else if (ModuleWarningSettings.ModuleIncludePathWarningLevel == WarningLevel.Error)
{
Logger.LogError($"Error: {message}", args);
AnyErrors = true;
}
}
void LoggerFuncPrivate(string? message, params object?[] args)
{
if (ModuleWarningSettings.ModuleIncludePrivateWarningLevel == WarningLevel.Warning)
{
Logger.LogWarning($"Warning: {message}", args);
}
else if (ModuleWarningSettings.ModuleIncludePrivateWarningLevel == WarningLevel.Error)
{
Logger.LogError($"Error: {message}", args);
AnyErrors = true;
}
}
void LoggerFuncSubDir(string? message, params object?[] args)
{
if (ModuleWarningSettings.ModuleIncludeSubdirectoryWarningLevel == WarningLevel.Warning)
{
Logger.LogWarning($"Warning: {message}", args);
}
else if (ModuleWarningSettings.ModuleIncludeSubdirectoryWarningLevel == WarningLevel.Error)
{
Logger.LogError($"Error: {message}", args);
AnyErrors = true;
}
}
IOrderedEnumerable PublicIncludePaths = Module.Rules.PublicIncludePaths.Select(x => DirectoryReference.FromString(x)!).OrderBy(x => x.FullName);
IOrderedEnumerable PrivateIncludePaths = Module.Rules.PrivateIncludePaths.Select(x => DirectoryReference.FromString(x)!).OrderBy(x => x.FullName);
IOrderedEnumerable InternalIncludePaths = Module.Rules.InternalIncludePaths.Select(x => DirectoryReference.FromString(x)!).OrderBy(x => x.FullName);
IOrderedEnumerable PublicSystemIncludePaths = Module.Rules.PublicSystemIncludePaths.Select(x => DirectoryReference.FromString(x)!).OrderBy(x => x.FullName);
IOrderedEnumerable OtherModules = AllModules.Where(x => x != Module).OrderBy(x => x.Name);
if (Module is UEBuildModuleExternal)
{
foreach (DirectoryReference Path in PublicIncludePaths)
{
LoggerFunc("External module '{Name}' is adding '{Path}' to PublicIncludePaths. This path should be added to PublicSystemIncludePaths.", Module.Name, Path.MakeRelativeTo(Module.ModuleDirectory));
}
foreach (DirectoryReference Path in PublicSystemIncludePaths.Where(x => !x.IsUnderDirectory(Module.ModuleDirectory)))
{
UEBuildModule? OtherModule = OtherModules.FirstOrDefault(x => Path.IsUnderDirectory(x.ModuleDirectory));
if (OtherModule is UEBuildModuleExternal)
{
LoggerFunc("External module '{Name}' is adding '{Path}' from external module '{OtherModule}' to PublicSystemIncludePaths. Did you intend to add a public reference?", Module.Name, Path, OtherModule.Name);
}
else if (OtherModule is UEBuildModuleCPP)
{
LoggerFunc("External module '{Name}' is adding '{Path}' from module '{OtherModule}' to PublicSystemIncludePaths. This is not allowed.", Module.Name, Path, OtherModule.Name);
}
}
foreach (DirectoryReference Path in PrivateIncludePaths)
{
LoggerFunc("External module '{Name}' is adding '{Path}' to PrivateIncludePaths. This path is unused.", Module.Name, Path);
}
foreach (DirectoryReference Path in InternalIncludePaths)
{
LoggerFunc("External module '{Name}' is adding '{Path}' to InternalIncludePaths. This path is unused.", Module.Name, Path);
}
}
else if (Module is UEBuildModuleCPP)
{
foreach (DirectoryReference Path in PublicIncludePaths)
{
if (Path.IsUnderDirectory(Module.ModuleDirectory))
{
if (Path == Module.ModuleDirectory)
{
LoggerFunc("Module '{Name}' is adding root directory to PublicIncludePaths. This is not allowed.", Module.Name);
}
else if (Path.IsUnderDirectory(DirectoryReference.Combine(Module.ModuleDirectory, "Private"))
|| Path.IsUnderDirectory(DirectoryReference.Combine(Module.ModuleDirectory, "Internal")))
{
LoggerFuncPrivate("Module '{Name}' is adding subdirectory '{Path}' to PublicIncludePaths. This is not allowed.", Module.Name, Path.MakeRelativeTo(Module.ModuleDirectory));
}
else if (Path.IsUnderDirectory(DirectoryReference.Combine(Module.ModuleDirectory, "Public"))
|| Path.IsUnderDirectory(DirectoryReference.Combine(Module.ModuleDirectory, "Classes")))
{
LoggerFuncSubDir("Module '{Name}' is adding subdirectory '{Path}' to PublicIncludePaths. This is not necessary.", Module.Name, Path.MakeRelativeTo(Module.ModuleDirectory));
}
}
UEBuildModule? OtherModule = OtherModules.FirstOrDefault(x => Path.IsUnderDirectory(x.ModuleDirectory));
if (OtherModule is UEBuildModuleExternal)
{
LoggerFunc("Module '{Name}' is adding '{Path}' from external module '{OtherModule}' to PublicIncludePaths. Did you intend to add a public reference?", Module.Name, Path, OtherModule.Name);
}
else if (OtherModule is UEBuildModuleCPP)
{
if (Path == OtherModule.ModuleDirectory)
{
LoggerFuncPrivate("Module '{Name}' is adding root directory from '{OtherModule}' to PublicIncludePaths. This is not allowed.", Module.Name, OtherModule.Name);
}
else if (Path.IsUnderDirectory(DirectoryReference.Combine(OtherModule.ModuleDirectory, "Private"))
| Path.IsUnderDirectory(DirectoryReference.Combine(OtherModule.ModuleDirectory, "Internal")))
{
LoggerFuncPrivate("Module '{Name}' is adding '{Path}' from module '{OtherModule}' to PublicIncludePaths. This is not allowed.", Module.Name, Path, OtherModule.Name);
}
else if (Path.IsUnderDirectory(DirectoryReference.Combine(OtherModule.ModuleDirectory, "Public"))
|| Path.IsUnderDirectory(DirectoryReference.Combine(OtherModule.ModuleDirectory, "Classes")))
{
LoggerFunc("Module '{Name}' is adding '{Path}' from module '{OtherModule}' to PublicIncludePaths. Did you intend to add a public reference?", Module.Name, Path, OtherModule.Name);
}
}
}
foreach (DirectoryReference Path in PrivateIncludePaths)
{
if (Path.IsUnderDirectory(Module.ModuleDirectory))
{
if (Path == Module.ModuleDirectory)
{
LoggerFunc("Module '{Name}' is adding root directory to PrivateIncludePaths. This is not recommended.", Module.Name);
}
else if (Path.IsUnderDirectory(DirectoryReference.Combine(Module.ModuleDirectory, "Private"))
|| Path.IsUnderDirectory(DirectoryReference.Combine(Module.ModuleDirectory, "Internal"))
|| Path.IsUnderDirectory(DirectoryReference.Combine(Module.ModuleDirectory, "Public"))
|| Path.IsUnderDirectory(DirectoryReference.Combine(Module.ModuleDirectory, "Classes")))
{
LoggerFuncSubDir("Module '{Name}' is adding subdirectory '{Path}' to PrivateIncludePaths. This is not necessary.", Module.Name, Path.MakeRelativeTo(Module.ModuleDirectory));
}
}
UEBuildModule? OtherModule = OtherModules.FirstOrDefault(x => Path.IsUnderDirectory(x.ModuleDirectory));
if (OtherModule is UEBuildModuleExternal)
{
LoggerFunc("Module '{Name}' is adding '{Path}' from external module '{OtherModule}' to PrivateIncludePaths. Did you intend to add a private reference?", Module.Name, Path, OtherModule.Name);
}
else if (OtherModule is UEBuildModuleCPP)
{
if (Path == OtherModule.ModuleDirectory)
{
LoggerFuncPrivate("Module '{Name}' is adding root directory from '{OtherModule}' to PrivateIncludePaths. This is not allowed.", Module.Name, OtherModule.Name);
}
else if (Path.IsUnderDirectory(DirectoryReference.Combine(OtherModule.ModuleDirectory, "Private"))
| Path.IsUnderDirectory(DirectoryReference.Combine(OtherModule.ModuleDirectory, "Internal")))
{
LoggerFuncPrivate("Module '{Name}' is adding '{Path}' from module '{OtherModule}' to PrivateIncludePaths. This is not allowed.", Module.Name, Path, OtherModule.Name);
}
else if (Path.IsUnderDirectory(DirectoryReference.Combine(OtherModule.ModuleDirectory, "Public"))
|| Path.IsUnderDirectory(DirectoryReference.Combine(OtherModule.ModuleDirectory, "Classes")))
{
LoggerFunc("Module '{Name}' is adding '{Path}' from module '{OtherModule}' to PrivateIncludePaths. Did you intend to add a private reference?", Module.Name, Path, OtherModule.Name);
}
}
}
foreach (DirectoryReference Path in InternalIncludePaths)
{
if (Path.IsUnderDirectory(Module.ModuleDirectory))
{
if (Path == Module.ModuleDirectory)
{
LoggerFunc("Module '{Name}' is adding root directory to InternalIncludePaths. This is not allowed.", Module.Name);
}
else if (Path.IsUnderDirectory(DirectoryReference.Combine(Module.ModuleDirectory, "Private"))
|| Path.IsUnderDirectory(DirectoryReference.Combine(Module.ModuleDirectory, "Internal")))
{
LoggerFunc("Module '{Name}' is adding subdirectory '{Path}' to InternalIncludePaths. This is not allowed.", Module.Name, Path.MakeRelativeTo(Module.ModuleDirectory));
}
else if (Path.IsUnderDirectory(DirectoryReference.Combine(Module.ModuleDirectory, "Public"))
|| Path.IsUnderDirectory(DirectoryReference.Combine(Module.ModuleDirectory, "Classes")))
{
LoggerFuncSubDir("Module '{Name}' is adding subdirectory '{Path}' to InternalIncludePaths. This is not necessary.", Module.Name, Path.MakeRelativeTo(Module.ModuleDirectory));
}
}
UEBuildModule? OtherModule = OtherModules.FirstOrDefault(x => Path.IsUnderDirectory(x.ModuleDirectory));
if (OtherModule is UEBuildModuleExternal)
{
LoggerFunc("Module '{Name}' is adding '{Path}' from external module '{OtherModule}' to InternalIncludePaths. Did you intend to add a public reference?", Module.Name, Path, OtherModule.Name);
}
else if (OtherModule is UEBuildModuleCPP)
{
if (Path == OtherModule.ModuleDirectory)
{
LoggerFunc("Module '{Name}' is adding root directory from '{OtherModule}' to InternalIncludePaths. This is not allowed.", Module.Name, OtherModule.Name);
}
else if (Path.IsUnderDirectory(DirectoryReference.Combine(OtherModule.ModuleDirectory, "Private"))
| Path.IsUnderDirectory(DirectoryReference.Combine(OtherModule.ModuleDirectory, "Internal")))
{
LoggerFunc("Module '{Name}' is adding '{Path}' from module '{OtherModule}' to InternalIncludePaths. This is not allowed.", Module.Name, Path, OtherModule.Name);
}
else if (Path.IsUnderDirectory(DirectoryReference.Combine(OtherModule.ModuleDirectory, "Public"))
|| Path.IsUnderDirectory(DirectoryReference.Combine(OtherModule.ModuleDirectory, "Classes")))
{
LoggerFunc("Module '{Name}' is adding '{Path}' from module '{OtherModule}' to InternalIncludePaths. Did you intend to add a public reference?", Module.Name, Path, OtherModule.Name);
}
}
}
}
return AnyErrors;
}
///
/// Return whether the given platform requires a monolithic build
///
/// The platform of interest
/// The configuration of interest
///
public static bool PlatformRequiresMonolithicBuilds(UnrealTargetPlatform InPlatform, UnrealTargetConfiguration InConfiguration)
{
// Some platforms require monolithic builds...
UEBuildPlatform? BuildPlatform;
if (TryGetBuildPlatform(InPlatform, out BuildPlatform))
{
return BuildPlatform.ShouldCompileMonolithicBinary(InPlatform);
}
// We assume it does not
return false;
}
///
/// Get the extension to use for the given binary type
///
/// The binary type being built
/// string The binary extension (i.e. 'exe' or 'dll')
public virtual string GetBinaryExtension(UEBuildBinaryType InBinaryType)
{
throw new BuildException("GetBinaryExtensiton for {0} not handled in {1}", InBinaryType.ToString(), ToString());
}
///
/// Get the extensions to use for debug info for the given binary type
///
/// Options for the target being built
/// The binary type being built
/// string[] The debug info extensions (i.e. 'pdb')
public virtual string[] GetDebugInfoExtensions(ReadOnlyTargetRules InTarget, UEBuildBinaryType InBinaryType)
{
throw new BuildException("GetDebugInfoExtensions for {0} not handled in {1}", InBinaryType.ToString(), ToString());
}
///
/// Whether this platform should build a monolithic binary
///
public virtual bool ShouldCompileMonolithicBinary(UnrealTargetPlatform InPlatform)
{
return false;
}
///
/// Modify the rules for a newly created module, where the target is a different host platform.
/// This is not required - but allows for hiding details of a particular platform.
///
/// The name of the module
/// The module rules
/// The target being build
public virtual void ModifyModuleRulesForOtherPlatform(string ModuleName, ModuleRules Rules, ReadOnlyTargetRules Target)
{
}
///
/// For platforms that need to output multiple files per binary (ie Android "fat" binaries)
/// this will emit multiple paths. By default, it simply makes an array from the input
///
public virtual List FinalizeBinaryPaths(FileReference BinaryName, FileReference? ProjectFile, ReadOnlyTargetRules Target)
{
List TempList = new List() { BinaryName };
return TempList;
}
///
/// Return all valid configurations for this platform
/// Typically, this is always Debug, Development, and Shipping - but Test is a likely future addition for some platforms
///
public virtual List GetConfigurations(UnrealTargetPlatform InUnrealTargetPlatform, bool bIncludeDebug)
{
List Configurations = new List()
{
UnrealTargetConfiguration.Development,
};
if (bIncludeDebug)
{
Configurations.Insert(0, UnrealTargetConfiguration.Debug);
}
return Configurations;
}
protected static bool DoProjectSettingsMatchDefault(UnrealTargetPlatform Platform, DirectoryReference ProjectDirectoryName, string Section, string[]? BoolKeys, string[]? IntKeys, string[]? StringKeys, ILogger Logger)
{
ConfigHierarchy ProjIni = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, ProjectDirectoryName, Platform);
ConfigHierarchy DefaultIni = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, (DirectoryReference?)null, Platform);
// look at all bool values
if (BoolKeys != null)
{
foreach (string Key in BoolKeys)
{
bool Default = false, Project = false;
DefaultIni.GetBool(Section, Key, out Default);
ProjIni.GetBool(Section, Key, out Project);
if (Default != Project)
{
Log.TraceInformationOnce("{0} is not set to default. (Base: {1} vs. {2}: {3})", Key, Default, Path.GetFileName(ProjectDirectoryName.FullName), Project);
return false;
}
}
}
// look at all int values
if (IntKeys != null)
{
foreach (string Key in IntKeys)
{
int Default = 0, Project = 0;
DefaultIni.GetInt32(Section, Key, out Default);
ProjIni.GetInt32(Section, Key, out Project);
if (Default != Project)
{
Log.TraceInformationOnce("{0} is not set to default. (Base: {1} vs. {2}: {3})", Key, Default, Path.GetFileName(ProjectDirectoryName.FullName), Project);
return false;
}
}
}
// look for all string values
if (StringKeys != null)
{
foreach (string Key in StringKeys)
{
string? Default = "", Project = "";
DefaultIni.GetString(Section, Key, out Default);
ProjIni.GetString(Section, Key, out Project);
if (Default != Project)
{
Log.TraceInformationOnce("{0} is not set to default. (Base: {1} vs. {2}: {3})", Key, Default, Path.GetFileName(ProjectDirectoryName.FullName), Project);
return false;
}
}
}
// if we get here, we match all important settings
return true;
}
///
/// Check for the default configuration
/// return true if the project uses the default build config
///
public virtual bool HasDefaultBuildConfig(UnrealTargetPlatform Platform, DirectoryReference ProjectDirectoryName)
{
string[] BoolKeys = new string[] {
"bCompileApex", "bCompileICU",
"bCompileRecast", "bCompileSpeedTree",
"bCompileWithPluginSupport", "bCompilePhysXVehicle", "bCompileFreeType",
"bCompileForSize", "bCompileCEF3", "bCompileCustomSQLitePlatform"
};
return DoProjectSettingsMatchDefault(Platform, ProjectDirectoryName, "/Script/BuildSettings.BuildSettings",
BoolKeys, null, null, Logger);
}
///
/// Check for whether we require a build for platform reasons
/// return true if the project requires a build
///
public virtual bool RequiresBuild(UnrealTargetPlatform Platform, DirectoryReference ProjectDirectoryName)
{
return false;
}
///
/// Get a list of extra modules the platform requires.
/// This is to allow undisclosed platforms to add modules they need without exposing information about the platform.
///
/// The target being build
/// List of extra modules the platform needs to add to the target
public virtual void AddExtraModules(ReadOnlyTargetRules Target, List ExtraModuleNames)
{
}
///
/// Modify the rules for a newly created module, in a target that's being built for this platform.
/// This is not required - but allows for hiding details of a particular platform.
///
/// The name of the module
/// The module rules
/// The target being build
public virtual void ModifyModuleRulesForActivePlatform(string ModuleName, ModuleRules Rules, ReadOnlyTargetRules Target)
{
}
///
/// Setup the target environment for building
///
/// Settings for the target being compiled
/// The compile environment for this target
/// The link environment for this target
public abstract void SetUpEnvironment(ReadOnlyTargetRules Target, CppCompileEnvironment CompileEnvironment, LinkEnvironment LinkEnvironment);
///
/// Setup the configuration environment for building
///
/// The target being built
/// The global compile environment
/// The global link environment
public virtual void SetUpConfigurationEnvironment(ReadOnlyTargetRules Target, CppCompileEnvironment GlobalCompileEnvironment, LinkEnvironment GlobalLinkEnvironment)
{
if (GlobalCompileEnvironment.bUseDebugCRT)
{
GlobalCompileEnvironment.Definitions.Add("_DEBUG=1"); // the engine doesn't use this, but lots of 3rd party stuff does
}
else
{
GlobalCompileEnvironment.Definitions.Add("NDEBUG=1"); // the engine doesn't use this, but lots of 3rd party stuff does
}
switch (Target.Configuration)
{
default:
case UnrealTargetConfiguration.Debug:
GlobalCompileEnvironment.Definitions.Add("UE_BUILD_DEBUG=1");
break;
case UnrealTargetConfiguration.DebugGame:
// Individual game modules can be switched to be compiled in debug as necessary. By default, everything is compiled in development.
case UnrealTargetConfiguration.Development:
GlobalCompileEnvironment.Definitions.Add("UE_BUILD_DEVELOPMENT=1");
break;
case UnrealTargetConfiguration.Shipping:
GlobalCompileEnvironment.Definitions.Add("UE_BUILD_SHIPPING=1");
break;
case UnrealTargetConfiguration.Test:
GlobalCompileEnvironment.Definitions.Add("UE_BUILD_TEST=1");
break;
}
// Create debug info based on the heuristics specified by the user.
GlobalCompileEnvironment.bCreateDebugInfo =
Target.DebugInfo != DebugInfoMode.None && ShouldCreateDebugInfo(Target);
GlobalLinkEnvironment.bCreateDebugInfo = GlobalCompileEnvironment.bCreateDebugInfo;
}
///
/// Allows the platform to return various build metadata that is not tracked by other means. If the returned string changes, the makefile will be invalidated.
///
/// The project file being built
/// String describing the current build metadata
public string GetExternalBuildMetadata(FileReference? ProjectFile)
{
StringBuilder Result = new StringBuilder();
GetExternalBuildMetadata(ProjectFile, Result);
return Result.ToString();
}
///
/// Allows the platform to return various build metadata that is not tracked by other means. If the returned string changes, the makefile will be invalidated.
///
/// The project file being built
/// String builder to contain build metadata
public virtual void GetExternalBuildMetadata(FileReference? ProjectFile, StringBuilder Metadata)
{
}
///
/// Allows the platform to modify the binary link environment before the binary is built
///
/// The binary link environment being created
/// The binary compile environment being used
/// The target rules in use
/// The toolchain being used
/// Action graph that is used to build the binary
public virtual void ModifyBinaryLinkEnvironment(LinkEnvironment BinaryLinkEnvironment, CppCompileEnvironment BinaryCompileEnvironment, ReadOnlyTargetRules Target, UEToolChain ToolChain, IActionGraphBuilder Graph)
{
}
///
/// Indicates whether this platform requires a .loadorder file to be generated for the build.
/// .loadorder files contain a list of dynamic modules and the exact order in which they should be loaded
/// to ensure that all dependencies are satisfied i.e. we don't attempt to load a module without loading
/// all its dependencies first.
/// As such, this file is only needed in modular builds on some platforms (depending on the way they implement dynamic modules such as DLLs).
///
/// The target rules in use
/// True if .loadorder file should be generated
public virtual bool RequiresLoadOrderManifest(ReadOnlyTargetRules Target)
{
return false;
}
///
/// Checks if platform is part of a given platform group
///
/// The platform to check
/// The platform group to check
/// True if platform is part of a platform group
internal static bool IsPlatformInGroup(UnrealTargetPlatform Platform, UnrealPlatformGroup PlatformGroup)
{
List? Platforms = UEBuildPlatform.GetPlatformsInGroup(PlatformGroup);
if (Platforms != null)
{
return Platforms.Contains(Platform);
}
else
{
return false;
}
}
///
/// Gets the SDK object that was passed in to the constructor
///
/// The SDK object
public UEBuildPlatformSDK? GetSDK()
{
return UEBuildPlatformSDK.GetSDKForPlatform(Platform.ToString());
}
///
/// Gets the SDK object that was passed in to the constructor to the UEBuildPlatform constructor for this platform
///
/// The SDK object
public static UEBuildPlatformSDK? GetSDK(UnrealTargetPlatform Platform)
{
return UEBuildPlatformSDK.GetSDKForPlatform(Platform.ToString());
}
///
/// Whether this platform should create debug information or not
///
/// The target being built
/// bool true if debug info should be generated, false if not
public abstract bool ShouldCreateDebugInfo(ReadOnlyTargetRules Target);
///
/// Creates a toolchain instance for this platform. There should be a single toolchain instance per-target, as their may be
/// state data and configuration cached between calls.
///
/// The target being built
/// New toolchain instance.
public abstract UEToolChain CreateToolChain(ReadOnlyTargetRules Target);
///
/// Deploys the given target
///
/// Receipt for the target being deployed
public abstract void Deploy(TargetReceipt Receipt);
}
}