// Copyright Epic Games, Inc. All Rights Reserved. using System; using System.Collections.Generic; using System.Text; using System.Diagnostics; using System.IO; using System.Linq; using EpicGames.Core; using System.Reflection; using System.Diagnostics.CodeAnalysis; using OpenTracing.Util; using Microsoft.Extensions.Logging; namespace UnrealBuildTool { 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; /// /// 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 ReadOnlyHashSet? CachedIncludedFolderNames; /// /// Cached copy of the list of folders to exclude for this platform /// private ReadOnlyHashSet? CachedExcludedFolderNames; /// /// Constructor. /// /// The enum value for this platform /// The SDK management object for this platform /// Logger for output public UEBuildPlatform(UnrealTargetPlatform InPlatform, UEBuildPlatformSDK SDK, ILogger InLogger) { Platform = InPlatform; Logger = InLogger; // check DDPI to see if the platform is enabled on this host platform string IniPlatformName = ConfigHierarchy.GetIniPlatformName(Platform); bool bIsEnabled = DataDrivenPlatformInfo.GetDataDrivenInfoForPlatform(IniPlatformName)?.bIsEnabled ?? true; // set up the SDK if the platform is enabled UEBuildPlatformSDK.RegisterSDKForPlatform(SDK, Platform.ToString(), bIsEnabled); if (bIsEnabled) { SDK.ManageAndValidateSDK(); } } /// /// Finds all the UEBuildPlatformFactory types in this assembly and uses them to register all the available platforms /// /// Whether to register platforms that are not installed /// Only register the host platform /// Logger for output public static void RegisterPlatforms(bool bIncludeNonInstalledPlatforms, bool bHostPlatformOnly, ILogger Logger) { // Initialize the installed platform info using (GlobalTracer.Instance.BuildSpan("Initializing InstalledPlatformInfo").StartActive()) { InstalledPlatformInfo.Initialize(); } // 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 ReadOnlyHashSet 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 = new ReadOnlyHashSet(Names, DirectoryReference.Comparer); } return CachedIncludedFolderNames; } /// /// Finds a list of folder names to exclude when building for this platform /// public ReadOnlyHashSet GetExcludedFolderNames() { if(CachedExcludedFolderNames == null) { CachedExcludedFolderNames = new ReadOnlyHashSet(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() { return UEBuildPlatform.GetSDK(Platform)!.HasRequiredSDKsInstalled(); } /// /// Whether this platform requires specific Visual Studio version. /// public virtual VCProjectFileFormat GetRequiredVisualStudioVersion() { return VCProjectFileFormat.Default; } /// /// Gets all the registered platforms /// /// Sequence of registered platforms public static IEnumerable GetRegisteredPlatforms() { return BuildPlatformDictionary.Keys; } /// /// Returns true if this platform is capable of building the specified architectures in a single pass /// (e.g. creating a fat binary). /// /// Architectures that are being built public virtual bool CanBuildArchitecturesInSinglePass(IEnumerable InArchitectures) { return false; } /// /// Get the default architecture for a project. This may be overriden on the command line to UBT. /// /// Optional project to read settings from public virtual string GetDefaultArchitecture(FileReference? ProjectFile) { // by default, use an empty architecture (which is really just a modifer to the platform for some paths/names) return ""; } /// /// Get name for architecture-specific directories (can be shorter than architecture name itself) /// public virtual string GetFolderNameForArchitecture(string Architecture) { // by default, use the architecture name return Architecture; } /// /// 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 /// True if it's available, false otherwise public static bool IsPlatformAvailable(UnrealTargetPlatform Platform) { return BuildPlatformDictionary.ContainsKey(Platform) && 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 /// True if it's available, false otherwise public static bool IsPlatformAvailableForTarget(UnrealTargetPlatform Platform, ReadOnlyTargetRules Target) { return IsPlatformAvailable(Platform) && 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. /// public static String GetPathVarDelimiter() { if (BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Linux || BuildHostPlatform.Current.Platform == UnrealTargetPlatform.LinuxArm64 || BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Mac) { return ":"; } if (BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Win64) { return ";"; } throw new InvalidOperationException($"PATH variable delimiter unknown for platform {BuildHostPlatform.Current.Platform}"); } /// /// 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 the parallel executor /// public virtual bool CanUseParallelExecutor() { return CanUseXGE(); } /// /// 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) { } /// /// 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(), this.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(), this.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) { } /// /// Allows the platform to override whether the architecture name should be appended to the name of binaries. /// /// True if the architecture name should be appended to the binary public virtual bool RequiresArchitectureSuffix() { return true; } /// /// 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.bDisableDebugInfo && 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) { } /// /// 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); } }