// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. using System; using System.Collections.Generic; using System.Text; using System.Diagnostics; using System.IO; using Microsoft.Win32; using System.Linq; using Tools.DotNETCommon; using Microsoft.VisualStudio.Setup.Configuration; using System.Runtime.InteropServices; namespace UnrealBuildTool { /// /// Available compiler toolchains on Windows platform /// public enum WindowsCompiler { /// /// Use the default compiler. A specific value will always be used outside of configuration classes. /// Default, /// /// Use Clang for Windows, using the clang-cl driver. /// Clang, /// /// Use the Intel C++ compiler /// Intel, /// /// Visual Studio 2015 (Visual C++ 14.0) /// VisualStudio2015_DEPRECATED, /// /// Visual Studio 2015 (Visual C++ 14.0) /// [Obsolete("UE4 does not support building Visual Studio 2015 targets from the 4.22 release onwards.")] VisualStudio2015 = VisualStudio2015_DEPRECATED, /// /// Visual Studio 2017 (Visual C++ 15.0) /// VisualStudio2017, /// /// Visual Studio 2019 (Visual C++ 16.0) /// VisualStudio2019, } /// /// Which static analyzer to use /// public enum WindowsStaticAnalyzer { /// /// Do not perform static analysis /// None, /// /// Use the built-in Visual C++ static analyzer /// VisualCpp, /// /// Use PVS-Studio for static analysis /// PVSStudio, } /// /// Windows-specific target settings /// public class WindowsTargetRules { /// /// Version of the compiler toolchain to use on Windows platform. A value of "default" will be changed to a specific version at UBT startup. /// [ConfigFile(ConfigHierarchyType.Engine, "/Script/WindowsTargetPlatform.WindowsTargetSettings", "CompilerVersion")] [XmlConfigFile(Category = "WindowsPlatform")] [CommandLine("-2015", Value = "VisualStudio2015")] [CommandLine("-2017", Value = "VisualStudio2017")] [CommandLine("-2019", Value = "VisualStudio2019")] public WindowsCompiler Compiler = WindowsCompiler.Default; /// /// The specific toolchain version to use. This may be a specific version number (eg. "14.13.26128") or the string "Latest" to select the newest available version. By default, we use the /// toolchain version indicated by WindowsPlatform.DefaultToolChainVersion if it is available, or the latest version otherwise. /// [XmlConfigFile(Category = "WindowsPlatform")] public string CompilerVersion = null; /// /// The specific Windows SDK version to use. This may be a specific version number (eg. "8.1", "10.0", or "10.0.10150.0") or the string "Latest" to select the newest available version. /// By default, we use the Windows SDK version indicated by WindowsPlatform.DefaultWindowsSdkVersion if it is available, or the latest version otherwise. /// [XmlConfigFile(Category = "WindowsPlatform")] public string WindowsSdkVersion = null; /// /// Value for the WINVER macro, defining the minimum supported Windows version. /// public int TargetWindowsVersion = 0x601; /// /// Enable PIX debugging (automatically disabled in Shipping and Test configs) /// [ConfigFile(ConfigHierarchyType.Engine, "/Script/WindowsTargetPlatform.WindowsTargetSettings", "bEnablePIXProfiling")] public bool bPixProfilingEnabled = true; /// /// The name of the company (author, provider) that created the project. /// [ConfigFile(ConfigHierarchyType.Game, "/Script/EngineSettings.GeneralProjectSettings", "CompanyName")] public string CompanyName; /// /// The project's copyright and/or trademark notices. /// [ConfigFile(ConfigHierarchyType.Game, "/Script/EngineSettings.GeneralProjectSettings", "CopyrightNotice")] public string CopyrightNotice; /// /// The product name. /// [ConfigFile(ConfigHierarchyType.Game, "/Script/EngineSettings.GeneralProjectSettings", "ProjectName")] public string ProductName; /// /// The static analyzer to use /// [XmlConfigFile(Category = "WindowsPlatform")] [CommandLine("-StaticAnalyzer")] public WindowsStaticAnalyzer StaticAnalyzer = WindowsStaticAnalyzer.None; /// /// Whether we should export a file containing .obj->source file mappings. /// [XmlConfigFile] [CommandLine("-ObjSrcMap")] public string ObjSrcMapFile = null; /// /// Provides a Module Definition File (.def) to the linker to describe various attributes of a DLL. /// Necessary when exporting functions by ordinal values instead of by name. /// public string ModuleDefinitionFile; /// /// Enables strict standard conformance mode (/permissive-) in VS2017+. /// [XmlConfigFile(Category = "WindowsPlatform")] [CommandLine("-Strict")] public bool bStrictConformanceMode = false; /// VS2015 updated some of the CRT definitions but not all of the Windows SDK has been updated to match. /// Microsoft provides legacy_stdio_definitions library to enable building with VS2015 until they fix everything up. public bool bNeedsLegacyStdioDefinitionsLib { get { return Compiler == WindowsCompiler.VisualStudio2015_DEPRECATED || Compiler == WindowsCompiler.VisualStudio2017 || Compiler == WindowsCompiler.VisualStudio2019 || Compiler == WindowsCompiler.Clang; } } /// /// The stack size when linking a non-editor target /// [RequiresUniqueBuildEnvironment] [ConfigFile(ConfigHierarchyType.Engine, "/Script/WindowsTargetPlatform.WindowsTargetSettings")] public int DefaultStackSize = 5000000; /// /// The stack size to commit when linking a non-editor target /// [RequiresUniqueBuildEnvironment] [ConfigFile(ConfigHierarchyType.Engine, "/Script/WindowsTargetPlatform.WindowsTargetSettings")] public int DefaultStackSizeCommit; /// /// Determines the amount of memory that the compiler allocates to construct precompiled headers (/Zm). /// [XmlConfigFile(Category = "WindowsPlatform")] public int PCHMemoryAllocationFactor = 0; /// /// True if we allow using addresses larger than 2GB on 32 bit builds /// public bool bBuildLargeAddressAwareBinary = true; /// /// Create an image that can be hot patched (/FUNCTIONPADMIN) /// public bool bCreateHotPatchableImage = false; /// /// Whether to put global symbols in their own sections (/Gw), allowing the linker to discard any that are unused. /// public bool bOptimizeGlobalData = true; /// /// (Experimental) Appends the -ftime-trace argument to the command line for Clang, to output a JSON file containing a timeline for the compile. /// See http://aras-p.info/blog/2019/01/16/time-trace-timeline-flame-chart-profiler-for-Clang/ for more info. /// [XmlConfigFile(Category = "WindowsPlatform")] public bool bClangTimeTrace = false; /// /// The Visual C++ environment to use for this target. Only initialized after all the target settings are finalized, in ValidateTarget(). /// internal VCEnvironment Environment; /// /// Directory containing the toolchain /// public string ToolChainDir { get { return (Environment == null)? null : Environment.ToolChainDir.FullName; } } /// /// The version number of the toolchain /// public string ToolChainVersion { get { return (Environment == null)? null : Environment.ToolChainVersion.ToString(); } } /// /// Root directory containing the Windows Sdk /// public string WindowsSdkDir { get { return (Environment == null)? null : Environment.WindowsSdkDir.FullName; } } /// /// When using a Visual Studio compiler, returns the version name as a string /// /// The Visual Studio compiler version name (e.g. "2015") public string GetVisualStudioCompilerVersionName() { switch (Compiler) { case WindowsCompiler.Clang: case WindowsCompiler.Intel: case WindowsCompiler.VisualStudio2015_DEPRECATED: case WindowsCompiler.VisualStudio2017: case WindowsCompiler.VisualStudio2019: return "2015"; // VS2017 is backwards compatible with VS2015 compiler default: throw new BuildException("Unexpected WindowsCompiler version for GetVisualStudioCompilerVersionName(). Either not using a Visual Studio compiler or switch block needs to be updated"); } } } /// /// Read-only wrapper for Windows-specific target settings /// public class ReadOnlyWindowsTargetRules { /// /// The private mutable settings object /// private WindowsTargetRules Inner; /// /// Constructor /// /// The settings object to wrap public ReadOnlyWindowsTargetRules(WindowsTargetRules Inner) { this.Inner = Inner; } /// /// Accessors for fields on the inner TargetRules instance /// #region Read-only accessor properties #if !__MonoCS__ #pragma warning disable CS1591 #endif public WindowsCompiler Compiler { get { return Inner.Compiler; } } public string CompilerVersion { get { return Inner.CompilerVersion; } } public string WindowsSdkVersion { get { return Inner.WindowsSdkVersion; } } public int TargetWindowsVersion { get { return Inner.TargetWindowsVersion; } } public bool bPixProfilingEnabled { get { return Inner.bPixProfilingEnabled; } } public string CompanyName { get { return Inner.CompanyName; } } public string CopyrightNotice { get { return Inner.CopyrightNotice; } } public string ProductName { get { return Inner.ProductName; } } public WindowsStaticAnalyzer StaticAnalyzer { get { return Inner.StaticAnalyzer; } } public string ObjSrcMapFile { get { return Inner.ObjSrcMapFile; } } public string ModuleDefinitionFile { get { return Inner.ModuleDefinitionFile; } } public bool bNeedsLegacyStdioDefinitionsLib { get { return Inner.bNeedsLegacyStdioDefinitionsLib; } } public bool bStrictConformanceMode { get { return Inner.bStrictConformanceMode; } } public int DefaultStackSize { get { return Inner.DefaultStackSize; } } public int DefaultStackSizeCommit { get { return Inner.DefaultStackSizeCommit; } } public int PCHMemoryAllocationFactor { get { return Inner.PCHMemoryAllocationFactor; } } public bool bBuildLargeAddressAwareBinary { get { return Inner.bBuildLargeAddressAwareBinary; } } public bool bCreateHotpatchableImage { get { return Inner.bCreateHotPatchableImage; } } public bool bOptimizeGlobalData { get { return Inner.bOptimizeGlobalData; } } public bool bClangTimeTrace { get { return Inner.bClangTimeTrace; } } public string GetVisualStudioCompilerVersionName() { return Inner.GetVisualStudioCompilerVersionName(); } internal VCEnvironment Environment { get { return Inner.Environment; } } public string ToolChainDir { get { return Inner.ToolChainDir; } } public string ToolChainVersion { get { return Inner.ToolChainVersion; } } public string WindowsSdkDir { get { return Inner.WindowsSdkDir; } } #if !__MonoCS__ #pragma warning restore CS1591 #endif #endregion } class WindowsPlatform : UEBuildPlatform { /// /// The default compiler version to be used, if installed. /// static readonly VersionNumber DefaultClangToolChainVersion = VersionNumber.Parse("7.1.0"); /// /// The default compiler version to be used, if installed. /// static readonly VersionNumber DefaultVisualStudioToolChainVersion = VersionNumber.Parse("14.16.27023"); /// /// The default Windows SDK version to be used, if installed. /// static readonly VersionNumber DefaultWindowsSdkVersion = VersionNumber.Parse("10.0.16299.0"); /// /// Cache of Visual Studio installation directories /// private static Dictionary> CachedVSInstallDirs = new Dictionary>(); /// /// Cache of Visual C++ installation directories /// private static Dictionary> CachedToolChainDirs = new Dictionary>(); /// /// Cache of Windows SDK installation directories /// private static IReadOnlyDictionary CachedWindowsSdkDirs; /// /// Cache of Universal CRT installation directories /// private static IReadOnlyDictionary CachedUniversalCrtDirs; /// /// True if we should use the Clang linker (LLD) when bCompileWithClang is enabled, otherwise we use the MSVC linker /// public static readonly bool bAllowClangLinker = false; /// /// True if we should use the Intel linker (xilink) when bCompileWithICL is enabled, otherwise we use the MSVC linker /// public static readonly bool bAllowICLLinker = true; WindowsPlatformSDK SDK; /// /// Constructor /// /// Creates a windows platform with the given enum value /// The default C++ platform to compile for /// The installed Windows SDK public WindowsPlatform(UnrealTargetPlatform InPlatform, CppPlatform InDefaultCppPlatform, WindowsPlatformSDK InSDK) : base(InPlatform, InDefaultCppPlatform) { SDK = InSDK; } /// /// Whether the required external SDKs are installed for this platform. Could be either a manual install or an AutoSDK. /// public override SDKStatus HasRequiredSDKsInstalled() { return SDK.HasRequiredSDKsInstalled(); } /// /// Reset a target's settings to the default /// /// public override void ResetTarget(TargetRules Target) { base.ResetTarget(Target); if(Target.Configuration != UnrealTargetConfiguration.Shipping) { Target.WindowsPlatform.bCreateHotPatchableImage = true; } } /// /// Validate a target's settings /// public override void ValidateTarget(TargetRules Target) { if (Target.GlobalDefinitions.Contains("USE_NULL_RHI=1")) { Target.bCompileCEF3 = false; } // Set the compiler version if necessary if (Target.WindowsPlatform.Compiler == WindowsCompiler.Default) { Target.WindowsPlatform.Compiler = GetDefaultCompiler(Target.ProjectFile); } // Disable linking if we're using a static analyzer if(Target.WindowsPlatform.StaticAnalyzer != WindowsStaticAnalyzer.None) { Target.bDisableLinking = true; } // Disable PCHs for PVS studio if(Target.WindowsPlatform.StaticAnalyzer == WindowsStaticAnalyzer.PVSStudio) { Target.bUsePCHFiles = false; } // Override PCH settings if (Target.WindowsPlatform.Compiler == WindowsCompiler.Clang) { // @todo clang: Shared PCHs don't work on clang yet because the PCH will have definitions assigned to different values // than the consuming translation unit. Unlike the warning in MSVC, this is a compile in Clang error which cannot be suppressed Target.bUseSharedPCHs = false; // @todo clang: PCH files aren't supported by "clang-cl" yet (no /Yc support, and "-x c++-header" cannot be specified) Target.bUsePCHFiles = false; } if (Target.WindowsPlatform.Compiler == WindowsCompiler.Intel) { Target.NumIncludedBytesPerUnityCPP = Math.Min(Target.NumIncludedBytesPerUnityCPP, 256 * 1024); Target.bUseSharedPCHs = false; Target.bUsePCHFiles = false; } // E&C support. if (Target.bSupportEditAndContinue || Target.bAdaptiveUnityEnablesEditAndContinue) { Target.bUseIncrementalLinking = true; } if (Target.bAdaptiveUnityEnablesEditAndContinue && !Target.bAdaptiveUnityDisablesPCH && !Target.bAdaptiveUnityCreatesDedicatedPCH) { throw new BuildException("bAdaptiveUnityEnablesEditAndContinue requires bAdaptiveUnityDisablesPCH or bAdaptiveUnityCreatesDedicatedPCH"); } // If we're using PDB files and PCHs, the generated code needs to be compiled with the same options as the PCH. if ((Target.bUsePDBFiles || Target.bSupportEditAndContinue) && Target.bUsePCHFiles) { Target.bDisableDebugInfoForGeneratedCode = false; } // Initialize the VC environment for the target, and set all the version numbers to the concrete values we chose. VCEnvironment Environment = VCEnvironment.Create(Target.WindowsPlatform.Compiler, DefaultCppPlatform, Target.WindowsPlatform.CompilerVersion, Target.WindowsPlatform.WindowsSdkVersion); Target.WindowsPlatform.Environment = Environment; Target.WindowsPlatform.Compiler = Environment.Compiler; Target.WindowsPlatform.CompilerVersion = Environment.CompilerVersion.ToString(); Target.WindowsPlatform.WindowsSdkVersion = Environment.WindowsSdkVersion.ToString(); // @Todo: Still getting reports of frequent OOM issues with this enabled as of 15.7. // // Enable fast PDB linking if we're on VS2017 15.7 or later. Previous versions have OOM issues with large projects. // if(!Target.bFormalBuild && !Target.bUseFastPDBLinking.HasValue && Target.WindowsPlatform.Compiler >= WindowsCompiler.VisualStudio2017) // { // VersionNumber Version; // DirectoryReference ToolChainDir; // if(TryGetVCToolChainDir(Target.WindowsPlatform.Compiler, Target.WindowsPlatform.CompilerVersion, out Version, out ToolChainDir) && Version >= new VersionNumber(14, 14, 26316)) // { // Target.bUseFastPDBLinking = true; // } // } } /// /// Gets the default compiler which should be used, if it's not set explicitly by the target, command line, or config file. /// /// The default compiler version internal static WindowsCompiler GetDefaultCompiler(FileReference ProjectFile) { // If there's no specific compiler set, try to pick the matching compiler for the selected IDE if(ProjectFileGeneratorSettings.Format != null) { foreach(ProjectFileFormat Format in ProjectFileGeneratorSettings.ParseFormatList(ProjectFileGeneratorSettings.Format)) { if (Format == ProjectFileFormat.VisualStudio2019) { return WindowsCompiler.VisualStudio2019; } else if (Format == ProjectFileFormat.VisualStudio2017) { return WindowsCompiler.VisualStudio2017; } } } // Also check the default format for the Visual Studio project generator object ProjectFormatObject; if (XmlConfig.TryGetValue(typeof(VCProjectFileGenerator), "Version", out ProjectFormatObject)) { VCProjectFileFormat ProjectFormat = (VCProjectFileFormat)ProjectFormatObject; if (ProjectFormat == VCProjectFileFormat.VisualStudio2019) { return WindowsCompiler.VisualStudio2019; } else if (ProjectFormat == VCProjectFileFormat.VisualStudio2017) { return WindowsCompiler.VisualStudio2017; } } // Check the editor settings too ProjectFileFormat PreferredAccessor; if(ProjectFileGenerator.GetPreferredSourceCodeAccessor(ProjectFile, out PreferredAccessor)) { if(PreferredAccessor == ProjectFileFormat.VisualStudio2019) { return WindowsCompiler.VisualStudio2019; } else if(PreferredAccessor == ProjectFileFormat.VisualStudio2017) { return WindowsCompiler.VisualStudio2017; } } // Second, default based on what's installed, test for 2015 first if (HasCompiler(WindowsCompiler.VisualStudio2017)) { return WindowsCompiler.VisualStudio2017; } if (HasCompiler(WindowsCompiler.VisualStudio2019)) { return WindowsCompiler.VisualStudio2019; } // If we do have a Visual Studio installation, but we're missing just the C++ parts, warn about that. DirectoryReference VSInstallDir; if (TryGetVSInstallDir(WindowsCompiler.VisualStudio2017, out VSInstallDir)) { Log.TraceWarning("Visual Studio 2017 is installed, but is missing the C++ toolchain. Please verify that the \"VC++ 2017 toolset\" component is selected in the Visual Studio 2017 installation options."); } else if (TryGetVSInstallDir(WindowsCompiler.VisualStudio2019, out VSInstallDir)) { Log.TraceWarning("Visual Studio 2019 is installed, but is missing the C++ toolchain. Please verify that the \"VC++ 2019 toolset\" component is selected in the Visual Studio 2019 installation options."); } else { Log.TraceWarning("No Visual C++ installation was found. Please download and install Visual Studio 2015 with C++ components."); } // Finally, default to VS2017 anyway return WindowsCompiler.VisualStudio2017; } /// /// Returns the human-readable name of the given compiler /// /// The compiler value /// Name of the compiler public static string GetCompilerName(WindowsCompiler Compiler) { switch (Compiler) { case WindowsCompiler.VisualStudio2015_DEPRECATED: return "Visual Studio 2015"; case WindowsCompiler.VisualStudio2017: return "Visual Studio 2017"; case WindowsCompiler.VisualStudio2019: return "Visual Studio 2019"; default: return Compiler.ToString(); } } /// /// Get the first Visual Studio install directory for the given compiler version. Note that it is possible for the compiler toolchain to be installed without /// Visual Studio. /// /// Version of the toolchain to look for. /// On success, the directory that Visual Studio is installed to. /// True if the directory was found, false otherwise. public static bool TryGetVSInstallDir(WindowsCompiler Compiler, out DirectoryReference InstallDir) { if (BuildHostPlatform.Current.Platform != UnrealTargetPlatform.Win64 && BuildHostPlatform.Current.Platform != UnrealTargetPlatform.Win32) { InstallDir = null; return false; } List InstallDirs = FindVSInstallDirs(Compiler); if(InstallDirs.Count == 0) { InstallDir = null; return false; } else { InstallDir = InstallDirs[0]; return true; } } /// /// Read the Visual Studio install directory for the given compiler version. Note that it is possible for the compiler toolchain to be installed without /// Visual Studio. /// /// Version of the toolchain to look for. /// List of directories containing Visual Studio installations public static List FindVSInstallDirs(WindowsCompiler Compiler) { List InstallDirs; if(!CachedVSInstallDirs.TryGetValue(Compiler, out InstallDirs)) { InstallDirs = new List(); if (BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Win64 || BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Win32) { if(Compiler == WindowsCompiler.VisualStudio2015_DEPRECATED) { // VS2015 just installs one toolchain; use that. DirectoryReference InstallDir; if(TryReadInstallDirRegistryKey32("Microsoft\\VisualStudio\\SxS\\VS7", "14.0", out InstallDir)) { InstallDirs.Add(InstallDir); } } else if(Compiler == WindowsCompiler.VisualStudio2017 || Compiler == WindowsCompiler.VisualStudio2019) { List PreReleaseInstallDirs = new List(); try { SetupConfiguration Setup = new SetupConfiguration(); IEnumSetupInstances Enumerator = Setup.EnumAllInstances(); ISetupInstance[] Instances = new ISetupInstance[1]; for(;;) { int NumFetched; Enumerator.Next(1, Instances, out NumFetched); if(NumFetched == 0) { break; } ISetupInstance2 Instance = (ISetupInstance2)Instances[0]; if((Instance.GetState() & InstanceState.Local) == InstanceState.Local) { string VersionString = Instance.GetInstallationVersion(); VersionNumber Version; if (VersionNumber.TryParse(VersionString, out Version)) { VersionNumber Version2019 = new VersionNumber(16); if(Compiler == WindowsCompiler.VisualStudio2019 && Version < Version2019) { continue; } else if(Compiler == WindowsCompiler.VisualStudio2017 && Version >= Version2019) { continue; } } ISetupInstanceCatalog Catalog = (ISetupInstanceCatalog)Instance as ISetupInstanceCatalog; if (Catalog != null && Catalog.IsPrerelease()) { PreReleaseInstallDirs.Add(new DirectoryReference(Instance.GetInstallationPath())); } else { InstallDirs.Add(new DirectoryReference(Instance.GetInstallationPath())); } } } } catch { } InstallDirs.AddRange(PreReleaseInstallDirs); } else { throw new BuildException("Unsupported compiler version ({0})", Compiler); } } CachedVSInstallDirs.Add(Compiler, InstallDirs); } return InstallDirs; } /// /// Determines the directory containing the MSVC toolchain /// /// Major version of the compiler to use /// Map of version number to directories public static Dictionary FindToolChainDirs(WindowsCompiler Compiler) { Dictionary ToolChainVersionToDir; if(!CachedToolChainDirs.TryGetValue(Compiler, out ToolChainVersionToDir)) { ToolChainVersionToDir = new Dictionary(); if (BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Win64 || BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Win32) { if(Compiler == WindowsCompiler.Clang) { // Check for a manual installation DirectoryReference InstallDir = DirectoryReference.Combine(DirectoryReference.GetSpecialFolder(Environment.SpecialFolder.ProgramFiles), "LLVM"); if(IsValidToolChainDirClang(InstallDir)) { FileReference CompilerFile = FileReference.Combine(InstallDir, "bin", "clang-cl.exe"); if(FileReference.Exists(CompilerFile)) { FileVersionInfo VersionInfo = FileVersionInfo.GetVersionInfo(CompilerFile.FullName); VersionNumber Version = new VersionNumber(VersionInfo.FileMajorPart, VersionInfo.FileMinorPart, VersionInfo.FileBuildPart); ToolChainVersionToDir[Version] = InstallDir; } } // Check for AutoSDK paths DirectoryReference AutoSdkDir; if(UEBuildPlatformSDK.TryGetHostPlatformAutoSDKDir(out AutoSdkDir)) { DirectoryReference ClangBaseDir = DirectoryReference.Combine(AutoSdkDir, "Win64", "LLVM"); if(DirectoryReference.Exists(ClangBaseDir)) { foreach(DirectoryReference ToolChainDir in DirectoryReference.EnumerateDirectories(ClangBaseDir)) { VersionNumber Version; if(VersionNumber.TryParse(ToolChainDir.GetDirectoryName(), out Version) && IsValidToolChainDirClang(ToolChainDir)) { ToolChainVersionToDir[Version] = ToolChainDir; } } } } } else if(Compiler == WindowsCompiler.Intel) { // Just check for a manual installation DirectoryReference InstallDir = DirectoryReference.Combine(DirectoryReference.GetSpecialFolder(Environment.SpecialFolder.ProgramFilesX86), "IntelSWTools", "compilers_and_libraries", "windows"); if(DirectoryReference.Exists(InstallDir)) { FileReference IclPath = FileReference.Combine(InstallDir, "bin", "intel64", "icl.exe"); if(FileReference.Exists(IclPath)) { FileVersionInfo VersionInfo = FileVersionInfo.GetVersionInfo(IclPath.FullName); VersionNumber Version = new VersionNumber(VersionInfo.FileMajorPart, VersionInfo.FileMinorPart, VersionInfo.FileBuildPart); ToolChainVersionToDir[Version] = InstallDir; } } } else if(Compiler == WindowsCompiler.VisualStudio2015_DEPRECATED) { // VS2015 just installs one toolchain; use that. List InstallDirs = FindVSInstallDirs(Compiler); foreach(DirectoryReference InstallDir in InstallDirs) { DirectoryReference ToolChainBaseDir = DirectoryReference.Combine(InstallDir, "VC"); if(IsValidToolChainDir2015(ToolChainBaseDir)) { ToolChainVersionToDir[new VersionNumber(14, 0)] = ToolChainBaseDir; } } } else if(Compiler == WindowsCompiler.VisualStudio2017 || Compiler == WindowsCompiler.VisualStudio2019) { // Enumerate all the manually installed toolchains List InstallDirs = FindVSInstallDirs(Compiler); foreach(DirectoryReference InstallDir in InstallDirs) { DirectoryReference ToolChainBaseDir = DirectoryReference.Combine(InstallDir, "VC", "Tools", "MSVC"); if(DirectoryReference.Exists(ToolChainBaseDir)) { foreach(DirectoryReference ToolChainDir in DirectoryReference.EnumerateDirectories(ToolChainBaseDir)) { VersionNumber Version; if(VersionNumber.TryParse(ToolChainDir.GetDirectoryName(), out Version) && IsValidToolChainDir2017or2019(ToolChainDir) && !ToolChainVersionToDir.ContainsKey(Version)) { ToolChainVersionToDir[Version] = ToolChainDir; } } } } // Enumerate all the AutoSDK toolchains DirectoryReference PlatformDir; if(UEBuildPlatformSDK.TryGetHostPlatformAutoSDKDir(out PlatformDir)) { DirectoryReference ToolChainBaseDir = DirectoryReference.Combine(PlatformDir, "Win64", (Compiler == WindowsCompiler.VisualStudio2019)? "VS2019" : "VS2017"); if(DirectoryReference.Exists(ToolChainBaseDir)) { foreach(DirectoryReference ToolChainDir in DirectoryReference.EnumerateDirectories(ToolChainBaseDir)) { VersionNumber Version; if(VersionNumber.TryParse(ToolChainDir.GetDirectoryName(), out Version) && IsValidToolChainDir2017or2019(ToolChainDir) && !ToolChainVersionToDir.ContainsKey(Version)) { ToolChainVersionToDir[Version] = ToolChainDir; } } } } } else { throw new BuildException("Unsupported compiler version ({0})", Compiler); } } CachedToolChainDirs.Add(Compiler, ToolChainVersionToDir); } return ToolChainVersionToDir; } /// /// Checks if the given directory contains a valid Clang toolchain /// /// Directory to check /// True if the given directory is valid static bool IsValidToolChainDirClang(DirectoryReference ToolChainDir) { return FileReference.Exists(FileReference.Combine(ToolChainDir, "bin", "clang-cl.exe")); } /// /// Checks if the given directory contains a valid Visual Studio 2015 toolchain /// /// Directory to check /// True if the given directory is valid static bool IsValidToolChainDir2015(DirectoryReference ToolChainDir) { return FileReference.Exists(FileReference.Combine(ToolChainDir, "bin", "amd64", "cl.exe")) || FileReference.Exists(FileReference.Combine(ToolChainDir, "bin", "x86_amd64", "cl.exe")); } /// /// Checks if the given directory contains a valid Visual Studio 2017 toolchain /// /// Directory to check /// True if the given directory is valid static bool IsValidToolChainDir2017or2019(DirectoryReference ToolChainDir) { return FileReference.Exists(FileReference.Combine(ToolChainDir, "bin", "Hostx86", "x64", "cl.exe")) || FileReference.Exists(FileReference.Combine(ToolChainDir, "bin", "Hostx64", "x64", "cl.exe")); } /// /// Determines if an IDE for the given compiler is installed. /// /// Compiler to check for /// True if the given compiler is installed public static bool HasIDE(WindowsCompiler Compiler) { return FindVSInstallDirs(Compiler).Count > 0; } /// /// Determines if a given compiler is installed /// /// Compiler to check for /// True if the given compiler is installed public static bool HasCompiler(WindowsCompiler Compiler) { return FindToolChainDirs(Compiler).Count > 0; } /// /// Determines the directory containing the MSVC toolchain /// /// Major version of the compiler to use /// The minimum compiler version to use /// Receives the chosen toolchain version /// Receives the directory containing the toolchain /// True if the toolchain directory was found correctly public static bool TryGetToolChainDir(WindowsCompiler Compiler, string CompilerVersion, out VersionNumber OutToolChainVersion, out DirectoryReference OutToolChainDir) { // Find all the installed toolchains Dictionary ToolChainVersionToDir = FindToolChainDirs(Compiler); // Figure out the actual version number that we want VersionNumber ToolChainVersion = null; if(CompilerVersion != null) { if(String.Compare(CompilerVersion, "Latest", StringComparison.InvariantCultureIgnoreCase) == 0 && ToolChainVersionToDir.Count > 0) { ToolChainVersion = ToolChainVersionToDir.OrderBy(x => x.Key).Last().Key; } else if(!VersionNumber.TryParse(CompilerVersion, out ToolChainVersion)) { throw new BuildException("Unable to find {0} toolchain; '{1}' is an invalid version", GetCompilerName(Compiler), CompilerVersion); } } else { VersionNumber DefaultToolChainVersion; if(Compiler == WindowsCompiler.Clang) { DefaultToolChainVersion = DefaultClangToolChainVersion; } else { DefaultToolChainVersion = DefaultVisualStudioToolChainVersion; } if(ToolChainVersionToDir.ContainsKey(DefaultToolChainVersion)) { ToolChainVersion = DefaultToolChainVersion; } else if(ToolChainVersionToDir.Count > 0) { ToolChainVersion = ToolChainVersionToDir.OrderBy(x => x.Key).Last().Key; } } // Get the actual directory for this version if(ToolChainVersion != null && ToolChainVersionToDir.TryGetValue(ToolChainVersion, out OutToolChainDir)) { OutToolChainVersion = ToolChainVersion; return true; } // Otherwise fail OutToolChainVersion = null; OutToolChainDir = null; return false; } /// /// Reads an install directory for a 32-bit program from a registry key. This checks for per-user and machine wide settings, and under the Wow64 virtual keys (HKCU\SOFTWARE, HKLM\SOFTWARE, HKCU\SOFTWARE\Wow6432Node, HKLM\SOFTWARE\Wow6432Node). /// /// Path to the key to read, under one of the roots listed above. /// Value to be read. /// On success, the directory corresponding to the value read. /// True if the key was read, false otherwise. static bool TryReadInstallDirRegistryKey32(string KeySuffix, string ValueName, out DirectoryReference InstallDir) { if (TryReadDirRegistryKey("HKEY_CURRENT_USER\\SOFTWARE\\" + KeySuffix, ValueName, out InstallDir)) { return true; } if (TryReadDirRegistryKey("HKEY_LOCAL_MACHINE\\SOFTWARE\\" + KeySuffix, ValueName, out InstallDir)) { return true; } if (TryReadDirRegistryKey("HKEY_CURRENT_USER\\SOFTWARE\\Wow6432Node\\" + KeySuffix, ValueName, out InstallDir)) { return true; } if (TryReadDirRegistryKey("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\" + KeySuffix, ValueName, out InstallDir)) { return true; } return false; } /// /// Attempts to reads a directory name stored in a registry key /// /// Key to read from /// Value within the key to read /// The directory read from the registry key /// True if the key was read, false if it was missing or empty static bool TryReadDirRegistryKey(string KeyName, string ValueName, out DirectoryReference Value) { string StringValue = Registry.GetValue(KeyName, ValueName, null) as string; if (String.IsNullOrEmpty(StringValue)) { Value = null; return false; } else { Value = new DirectoryReference(StringValue); return true; } } /// /// Gets the path to MSBuild. This mirrors the logic in GetMSBuildPath.bat. /// /// On success, receives the path to the MSBuild executable. /// True on success. public static bool TryGetMsBuildPath(out FileReference OutLocation) { // Get the Visual Studio 2017 install directory List InstallDirs = WindowsPlatform.FindVSInstallDirs(WindowsCompiler.VisualStudio2017); foreach(DirectoryReference InstallDir in InstallDirs) { FileReference MsBuildLocation = FileReference.Combine(InstallDir, "MSBuild", "15.0", "Bin", "MSBuild.exe"); if(FileReference.Exists(MsBuildLocation)) { OutLocation = MsBuildLocation; return true; } } // Try to get the MSBuild 14.0 path directly (see https://msdn.microsoft.com/en-us/library/hh162058(v=vs.120).aspx) FileReference ToolPath = FileReference.Combine(DirectoryReference.GetSpecialFolder(Environment.SpecialFolder.ProgramFilesX86), "MSBuild", "14.0", "bin", "MSBuild.exe"); if(FileReference.Exists(ToolPath)) { OutLocation = ToolPath; return true; } // Check for older versions of MSBuild. These are registered as separate versions in the registry. if (TryReadMsBuildInstallPath("Microsoft\\MSBuild\\ToolsVersions\\14.0", "MSBuildToolsPath", "MSBuild.exe", out ToolPath)) { OutLocation = ToolPath; return true; } if (TryReadMsBuildInstallPath("Microsoft\\MSBuild\\ToolsVersions\\12.0", "MSBuildToolsPath", "MSBuild.exe", out ToolPath)) { OutLocation = ToolPath; return true; } if (TryReadMsBuildInstallPath("Microsoft\\MSBuild\\ToolsVersions\\4.0", "MSBuildToolsPath", "MSBuild.exe", out ToolPath)) { OutLocation = ToolPath; return true; } OutLocation = null; return false; } /// /// Gets the MSBuild path, and throws an exception on failure. /// /// Path to MSBuild public static FileReference GetMsBuildToolPath() { FileReference Location; if(!TryGetMsBuildPath(out Location)) { throw new BuildException("Unable to find installation of MSBuild."); } return Location; } /// /// Function to query the registry under HKCU/HKLM Win32/Wow64 software registry keys for a certain install directory. /// This mirrors the logic in GetMSBuildPath.bat. /// /// static bool TryReadMsBuildInstallPath(string KeyRelativePath, string KeyName, string MsBuildRelativePath, out FileReference OutMsBuildPath) { string[] KeyBasePaths = { @"HKEY_CURRENT_USER\SOFTWARE\", @"HKEY_LOCAL_MACHINE\SOFTWARE\", @"HKEY_CURRENT_USER\SOFTWARE\Wow6432Node\", @"HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\" }; foreach (string KeyBasePath in KeyBasePaths) { string Value = Registry.GetValue(KeyBasePath + KeyRelativePath, KeyName, null) as string; if (Value != null) { FileReference MsBuildPath = FileReference.Combine(new DirectoryReference(Value), MsBuildRelativePath); if (FileReference.Exists(MsBuildPath)) { OutMsBuildPath = MsBuildPath; return true; } } } OutMsBuildPath = null; return false; } /// /// Updates the CachedWindowsSdkDirs and CachedUniversalCrtDirs variables /// private static void UpdateCachedWindowsSdks() { Dictionary WindowsSdkDirs = new Dictionary(); Dictionary UniversalCrtDirs = new Dictionary(); // Enumerate the Windows 8.1 SDK, if present DirectoryReference InstallDir_8_1; if(TryReadInstallDirRegistryKey32("Microsoft\\Microsoft SDKs\\Windows\\v8.1", "InstallationFolder", out InstallDir_8_1)) { if(FileReference.Exists(FileReference.Combine(InstallDir_8_1, "Include", "um", "windows.h"))) { Log.TraceLog("Found Windows 8.1 SDK at {0}", InstallDir_8_1); VersionNumber Version_8_1 = new VersionNumber(8, 1); WindowsSdkDirs[Version_8_1] = InstallDir_8_1; } } // Find all the root directories for Windows 10 SDKs List InstallDirs_10 = new List(); EnumerateSdkRootDirs(InstallDirs_10); // Enumerate all the Windows 10 SDKs foreach(DirectoryReference InstallDir_10 in InstallDirs_10.Distinct()) { DirectoryReference IncludeRootDir = DirectoryReference.Combine(InstallDir_10, "Include"); if(DirectoryReference.Exists(IncludeRootDir)) { foreach(DirectoryReference IncludeDir in DirectoryReference.EnumerateDirectories(IncludeRootDir)) { VersionNumber IncludeVersion; if(VersionNumber.TryParse(IncludeDir.GetDirectoryName(), out IncludeVersion)) { if(FileReference.Exists(FileReference.Combine(IncludeDir, "um", "windows.h"))) { Log.TraceLog("Found Windows 10 SDK version {0} at {1}", IncludeVersion, InstallDir_10); WindowsSdkDirs[IncludeVersion] = InstallDir_10; } if(FileReference.Exists(FileReference.Combine(IncludeDir, "ucrt", "corecrt.h"))) { Log.TraceLog("Found Universal CRT version {0} at {1}", IncludeVersion, InstallDir_10); UniversalCrtDirs[IncludeVersion] = InstallDir_10; } } } } } CachedWindowsSdkDirs = WindowsSdkDirs; CachedUniversalCrtDirs = UniversalCrtDirs; } /// /// Finds all the installed Windows SDK versions /// /// Map of version number to Windows SDK directories public static IReadOnlyDictionary FindWindowsSdkDirs() { // Update the cache of install directories, if it's not set if(CachedWindowsSdkDirs == null) { UpdateCachedWindowsSdks(); } return CachedWindowsSdkDirs; } /// /// Finds all the installed Universal CRT versions /// /// Map of version number to universal CRT directories public static IReadOnlyDictionary FindUniversalCrtDirs() { if(CachedUniversalCrtDirs == null) { UpdateCachedWindowsSdks(); } return CachedUniversalCrtDirs; } /// /// Enumerates all the Windows 10 SDK root directories /// /// Receives all the Windows 10 sdk root directories private static void EnumerateSdkRootDirs(List RootDirs) { DirectoryReference RootDir; if(TryReadInstallDirRegistryKey32("Microsoft\\Windows Kits\\Installed Roots", "KitsRoot10", out RootDir)) { Log.TraceLog("Found Windows 10 SDK root at {0} (1)", RootDir); RootDirs.Add(RootDir); } if(TryReadInstallDirRegistryKey32("Microsoft\\Microsoft SDKs\\Windows\\v10.0", "InstallationFolder", out RootDir)) { Log.TraceLog("Found Windows 10 SDK root at {0} (2)", RootDir); RootDirs.Add(RootDir); } DirectoryReference HostAutoSdkDir; if(UEBuildPlatformSDK.TryGetHostPlatformAutoSDKDir(out HostAutoSdkDir)) { DirectoryReference RootDirAutoSdk = DirectoryReference.Combine(HostAutoSdkDir, "Win64", "Windows Kits", "10"); if(DirectoryReference.Exists(RootDirAutoSdk)) { Log.TraceLog("Found Windows 10 AutoSDK root at {0}", RootDirAutoSdk); RootDirs.Add(RootDirAutoSdk); } } } /// /// Determines the directory containing the Windows SDK toolchain /// /// The desired Windows SDK version. This may be "Latest", a specific version number, or null. If null, the function will look for DefaultWindowsSdkVersion. Failing that, it will return the latest version. /// Receives the version number of the selected Windows SDK /// Receives the root directory for the selected SDK /// True if the toolchain directory was found correctly public static bool TryGetWindowsSdkDir(string DesiredVersion, out VersionNumber OutSdkVersion, out DirectoryReference OutSdkDir) { // Get a map of Windows SDK versions to their root directories IReadOnlyDictionary WindowsSdkDirs = FindWindowsSdkDirs(); // Figure out which version number to look for VersionNumber WindowsSdkVersion = null; if(DesiredVersion != null) { if(String.Compare(DesiredVersion, "Latest", StringComparison.InvariantCultureIgnoreCase) == 0 && CachedWindowsSdkDirs.Count > 0) { WindowsSdkVersion = CachedWindowsSdkDirs.OrderBy(x => x.Key).Last().Key; } else if(!VersionNumber.TryParse(DesiredVersion, out WindowsSdkVersion)) { throw new BuildException("Unable to find requested Windows SDK; '{0}' is an invalid version", DesiredVersion); } } else { if(CachedWindowsSdkDirs.ContainsKey(DefaultWindowsSdkVersion)) { WindowsSdkVersion = DefaultWindowsSdkVersion; } else if(CachedWindowsSdkDirs.Count > 0) { WindowsSdkVersion = CachedWindowsSdkDirs.OrderBy(x => x.Key).Last().Key; } } // Get the actual directory for this version DirectoryReference SdkDir; if(WindowsSdkVersion != null && CachedWindowsSdkDirs.TryGetValue(WindowsSdkVersion, out SdkDir)) { OutSdkDir = SdkDir; OutSdkVersion = WindowsSdkVersion; return true; } else { OutSdkDir = null; OutSdkVersion = null; return false; } } /// /// Gets the installation directory for the NETFXSDK /// /// Receives the installation directory on success /// True if the directory was found, false otherwise public static bool TryGetNetFxSdkInstallDir(out DirectoryReference OutInstallDir) { DirectoryReference HostAutoSdkDir; if(UEBuildPlatformSDK.TryGetHostPlatformAutoSDKDir(out HostAutoSdkDir)) { DirectoryReference NetFxDir_4_6 = DirectoryReference.Combine(HostAutoSdkDir, "Win64", "Windows Kits", "NETFXSDK", "4.6"); if(FileReference.Exists(FileReference.Combine(NetFxDir_4_6, "Include", "um", "mscoree.h"))) { OutInstallDir = NetFxDir_4_6; return true; } DirectoryReference NetFxDir_4_6_1 = DirectoryReference.Combine(HostAutoSdkDir, "Win64", "Windows Kits", "NETFXSDK", "4.6.1"); if(FileReference.Exists(FileReference.Combine(NetFxDir_4_6_1, "Include", "um", "mscoree.h"))) { OutInstallDir = NetFxDir_4_6_1; return true; } } return TryReadInstallDirRegistryKey32("Microsoft\\Microsoft SDKs\\NETFXSDK\\4.6", "KitsInstallationFolder", out OutInstallDir) || TryReadInstallDirRegistryKey32("Microsoft\\Microsoft SDKs\\NETFXSDK\\4.6.1", "KitsInstallationFolder", out OutInstallDir) || TryReadInstallDirRegistryKey32("Microsoft\\Microsoft SDKs\\NETFXSDK\\4.6.2", "KitsInstallationFolder", out OutInstallDir); } /// /// If this platform can be compiled with SN-DBS /// public override bool CanUseSNDBS() { return true; } /// /// 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. "UE4Editor", "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 override bool IsBuildProduct(string FileName, string[] NamePrefixes, string[] NameSuffixes) { return IsBuildProductName(FileName, NamePrefixes, NameSuffixes, ".exe") || IsBuildProductName(FileName, NamePrefixes, NameSuffixes, ".dll") || IsBuildProductName(FileName, NamePrefixes, NameSuffixes, ".dll.response") || IsBuildProductName(FileName, NamePrefixes, NameSuffixes, ".lib") || IsBuildProductName(FileName, NamePrefixes, NameSuffixes, ".pdb") || IsBuildProductName(FileName, NamePrefixes, NameSuffixes, ".exp") || IsBuildProductName(FileName, NamePrefixes, NameSuffixes, ".obj") || IsBuildProductName(FileName, NamePrefixes, NameSuffixes, ".map") || IsBuildProductName(FileName, NamePrefixes, NameSuffixes, ".objpaths"); } /// /// Get the extension to use for the given binary type /// /// The binrary type being built /// string The binary extenstion (ie 'exe' or 'dll') public override string GetBinaryExtension(UEBuildBinaryType InBinaryType) { switch (InBinaryType) { case UEBuildBinaryType.DynamicLinkLibrary: return ".dll"; case UEBuildBinaryType.Executable: return ".exe"; case UEBuildBinaryType.StaticLibrary: return ".lib"; } return base.GetBinaryExtension(InBinaryType); } /// /// Get the extensions to use for debug info for the given binary type /// /// The target being built /// The binary type being built /// string[] The debug info extensions (i.e. 'pdb') public override string[] GetDebugInfoExtensions(ReadOnlyTargetRules Target, UEBuildBinaryType InBinaryType) { switch (InBinaryType) { case UEBuildBinaryType.DynamicLinkLibrary: case UEBuildBinaryType.Executable: return new string[] {".pdb"}; } return new string [] {}; } public override bool HasDefaultBuildConfig(UnrealTargetPlatform Platform, DirectoryReference ProjectPath) { if (Platform == UnrealTargetPlatform.Win32) { string[] StringKeys = new string[] { "MinimumOSVersion" }; // look up OS specific settings if (!DoProjectSettingsMatchDefault(Platform, ProjectPath, "/Script/WindowsTargetPlatform.WindowsTargetSettings", null, null, StringKeys)) { return false; } } // check the base settings return base.HasDefaultBuildConfig(Platform, ProjectPath); } /// /// 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 override void ModifyModuleRulesForOtherPlatform(string ModuleName, ModuleRules Rules, ReadOnlyTargetRules Target) { } /// /// Gets the application icon for a given project /// /// The project file /// The icon to use for this project public static FileReference GetApplicationIcon(FileReference ProjectFile) { // Check if there's a custom icon if(ProjectFile != null) { FileReference IconFile = FileReference.Combine(ProjectFile.Directory, "Build", "Windows", "Application.ico"); if(FileReference.Exists(IconFile)) { return IconFile; } } // Otherwise use the default return FileReference.Combine(UnrealBuildTool.EngineDirectory, "Build", "Windows", "Resources", "Default.ico"); } /// /// 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 override void ModifyModuleRulesForActivePlatform(string ModuleName, ModuleRules Rules, ReadOnlyTargetRules Target) { bool bBuildShaderFormats = Target.bForceBuildShaderFormats; if (!Target.bBuildRequiresCookedData) { if (ModuleName == "TargetPlatform") { bBuildShaderFormats = true; } } // allow standalone tools to use target platform modules, without needing Engine if (ModuleName == "TargetPlatform") { if (Target.bForceBuildTargetPlatforms) { Rules.DynamicallyLoadedModuleNames.Add("WindowsTargetPlatform"); Rules.DynamicallyLoadedModuleNames.Add("WindowsNoEditorTargetPlatform"); Rules.DynamicallyLoadedModuleNames.Add("WindowsServerTargetPlatform"); Rules.DynamicallyLoadedModuleNames.Add("WindowsClientTargetPlatform"); Rules.DynamicallyLoadedModuleNames.Add("AllDesktopTargetPlatform"); } if (bBuildShaderFormats) { Rules.DynamicallyLoadedModuleNames.Add("ShaderFormatD3D"); Rules.DynamicallyLoadedModuleNames.Add("ShaderFormatOpenGL"); Rules.DynamicallyLoadedModuleNames.Remove("VulkanRHI"); Rules.DynamicallyLoadedModuleNames.Add("VulkanShaderFormat"); } } if (ModuleName == "D3D11RHI") { // To enable platform specific D3D11 RHI Types Rules.PrivateIncludePaths.Add("Runtime/Windows/D3D11RHI/Private/Windows"); } if (ModuleName == "D3D12RHI") { if (Target.WindowsPlatform.bPixProfilingEnabled && Target.Platform == UnrealTargetPlatform.Win64 && Target.Configuration != UnrealTargetConfiguration.Shipping && Target.Configuration != UnrealTargetConfiguration.Test) { // Define to indicate profiling enabled (64-bit only) Rules.PublicDefinitions.Add("D3D12_PROFILING_ENABLED=1"); Rules.PublicDefinitions.Add("PROFILE"); } else { Rules.PublicDefinitions.Add("D3D12_PROFILING_ENABLED=0"); } } // Delay-load D3D12 so we can use the latest features and still run on downlevel versions of the OS Rules.PublicDelayLoadDLLs.Add("d3d12.dll"); } /// /// 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 override void SetUpEnvironment(ReadOnlyTargetRules Target, CppCompileEnvironment CompileEnvironment, LinkEnvironment LinkEnvironment) { CompileEnvironment.Definitions.Add("WIN32=1"); CompileEnvironment.Definitions.Add(String.Format("_WIN32_WINNT=0x{0:X4}", Target.WindowsPlatform.TargetWindowsVersion)); CompileEnvironment.Definitions.Add(String.Format("WINVER=0x{0:X4}", Target.WindowsPlatform.TargetWindowsVersion)); CompileEnvironment.Definitions.Add("PLATFORM_WINDOWS=1"); FileReference MorpheusShaderPath = FileReference.Combine(UnrealBuildTool.EngineDirectory, "Shaders", "Private", "Platform", "PS4", "PostProcessHMDMorpheus.usf"); if (FileReference.Exists(MorpheusShaderPath)) { CompileEnvironment.Definitions.Add("HAS_MORPHEUS=1"); //on PS4 the SDK now handles distortion correction. On PC we will still have to handle it manually, CompileEnvironment.Definitions.Add("MORPHEUS_ENGINE_DISTORTION=1"); } // Add path to Intel math libraries when using ICL based on target platform if (Target.WindowsPlatform.Compiler == WindowsCompiler.Intel) { string Result = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "IntelSWTools", "compilers_and_libraries", "windows", "compiler", "lib", Target.Platform == UnrealTargetPlatform.Win32 ? "ia32" : "intel64"); if (!Directory.Exists(Result)) { throw new BuildException("ICL was selected but the required math libraries were not found. Could not find: " + Result); } LinkEnvironment.LibraryPaths.Add(new DirectoryReference(Result)); } // Explicitly exclude the MS C++ runtime libraries we're not using, to ensure other libraries we link with use the same // runtime library as the engine. bool bUseDebugCRT = Target.Configuration == UnrealTargetConfiguration.Debug && Target.bDebugBuildsActuallyUseDebugCRT; if (!Target.bUseStaticCRT || bUseDebugCRT) { LinkEnvironment.ExcludedLibraries.Add("LIBCMT"); LinkEnvironment.ExcludedLibraries.Add("LIBCPMT"); } if (!Target.bUseStaticCRT || !bUseDebugCRT) { LinkEnvironment.ExcludedLibraries.Add("LIBCMTD"); LinkEnvironment.ExcludedLibraries.Add("LIBCPMTD"); } if (Target.bUseStaticCRT || bUseDebugCRT) { LinkEnvironment.ExcludedLibraries.Add("MSVCRT"); LinkEnvironment.ExcludedLibraries.Add("MSVCPRT"); } if (Target.bUseStaticCRT || !bUseDebugCRT) { LinkEnvironment.ExcludedLibraries.Add("MSVCRTD"); LinkEnvironment.ExcludedLibraries.Add("MSVCPRTD"); } LinkEnvironment.ExcludedLibraries.Add("LIBC"); LinkEnvironment.ExcludedLibraries.Add("LIBCP"); LinkEnvironment.ExcludedLibraries.Add("LIBCD"); LinkEnvironment.ExcludedLibraries.Add("LIBCPD"); //@todo ATL: Currently, only VSAccessor requires ATL (which is only used in editor builds) // When compiling games, we do not want to include ATL - and we can't when compiling games // made with Launcher build due to VS 2012 Express not including ATL. // If more modules end up requiring ATL, this should be refactored into a BuildTarget flag (bNeedsATL) // that is set by the modules the target includes to allow for easier tracking. // Alternatively, if VSAccessor is modified to not require ATL than we should always exclude the libraries. if (Target.LinkType == TargetLinkType.Monolithic && (Target.Type == TargetType.Game || Target.Type == TargetType.Client || Target.Type == TargetType.Server)) { LinkEnvironment.ExcludedLibraries.Add("atl"); LinkEnvironment.ExcludedLibraries.Add("atls"); LinkEnvironment.ExcludedLibraries.Add("atlsd"); LinkEnvironment.ExcludedLibraries.Add("atlsn"); LinkEnvironment.ExcludedLibraries.Add("atlsnd"); } // Add the library used for the delayed loading of DLLs. LinkEnvironment.AdditionalLibraries.Add("delayimp.lib"); //@todo - remove once FB implementation uses Http module if (Target.bCompileAgainstEngine) { // link against wininet (used by FBX and Facebook) LinkEnvironment.AdditionalLibraries.Add("wininet.lib"); } // Compile and link with Win32 API libraries. LinkEnvironment.AdditionalLibraries.Add("rpcrt4.lib"); //LinkEnvironment.AdditionalLibraries.Add("wsock32.lib"); LinkEnvironment.AdditionalLibraries.Add("ws2_32.lib"); LinkEnvironment.AdditionalLibraries.Add("dbghelp.lib"); LinkEnvironment.AdditionalLibraries.Add("comctl32.lib"); LinkEnvironment.AdditionalLibraries.Add("Winmm.lib"); LinkEnvironment.AdditionalLibraries.Add("kernel32.lib"); LinkEnvironment.AdditionalLibraries.Add("user32.lib"); LinkEnvironment.AdditionalLibraries.Add("gdi32.lib"); LinkEnvironment.AdditionalLibraries.Add("winspool.lib"); LinkEnvironment.AdditionalLibraries.Add("comdlg32.lib"); LinkEnvironment.AdditionalLibraries.Add("advapi32.lib"); LinkEnvironment.AdditionalLibraries.Add("shell32.lib"); LinkEnvironment.AdditionalLibraries.Add("ole32.lib"); LinkEnvironment.AdditionalLibraries.Add("oleaut32.lib"); LinkEnvironment.AdditionalLibraries.Add("uuid.lib"); LinkEnvironment.AdditionalLibraries.Add("odbc32.lib"); LinkEnvironment.AdditionalLibraries.Add("odbccp32.lib"); LinkEnvironment.AdditionalLibraries.Add("netapi32.lib"); LinkEnvironment.AdditionalLibraries.Add("iphlpapi.lib"); LinkEnvironment.AdditionalLibraries.Add("setupapi.lib"); // Required for access monitor device enumeration // Windows Vista/7 Desktop Windows Manager API for Slate Windows Compliance LinkEnvironment.AdditionalLibraries.Add("dwmapi.lib"); // IME LinkEnvironment.AdditionalLibraries.Add("imm32.lib"); // For 64-bit builds, we'll forcibly ignore a linker warning with DirectInput. This is // Microsoft's recommended solution as they don't have a fixed .lib for us. if (Target.Platform == UnrealTargetPlatform.Win64) { LinkEnvironment.AdditionalArguments += " /ignore:4078"; } // Set up default stack size LinkEnvironment.DefaultStackSize = Target.WindowsPlatform.DefaultStackSize; LinkEnvironment.DefaultStackSizeCommit = Target.WindowsPlatform.DefaultStackSizeCommit; LinkEnvironment.ModuleDefinitionFile = Target.WindowsPlatform.ModuleDefinitionFile; } /// /// Setup the configuration environment for building /// /// The target being built /// The global compile environment /// The global link environment public override 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 } UnrealTargetConfiguration CheckConfig = Target.Configuration; switch (CheckConfig) { default: case UnrealTargetConfiguration.Debug: GlobalCompileEnvironment.Definitions.Add("UE_BUILD_DEBUG=1"); break; case UnrealTargetConfiguration.DebugGame: // Default to Development; can be overridden by individual modules. 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); // NOTE: Even when debug info is turned off, we currently force the linker to generate debug info // anyway on Visual C++ platforms. This will cause a PDB file to be generated with symbols // for most of the classes and function/method names, so that crashes still yield somewhat // useful call stacks, even though compiler-generate debug info may be disabled. This gives // us much of the build-time savings of fully-disabled debug info, without giving up call // data completely. GlobalLinkEnvironment.bCreateDebugInfo = true; } /// /// 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 override bool ShouldCreateDebugInfo(ReadOnlyTargetRules Target) { switch (Target.Configuration) { case UnrealTargetConfiguration.Development: case UnrealTargetConfiguration.Shipping: case UnrealTargetConfiguration.Test: return !Target.bOmitPCDebugInfoInDevelopment; case UnrealTargetConfiguration.DebugGame: case UnrealTargetConfiguration.Debug: default: return true; }; } /// /// Creates a toolchain instance for the given platform. /// /// The platform to create a toolchain for /// The target being built /// New toolchain instance. public override UEToolChain CreateToolChain(CppPlatform CppPlatform, ReadOnlyTargetRules Target) { if (Target.WindowsPlatform.StaticAnalyzer == WindowsStaticAnalyzer.PVSStudio) { return new PVSToolChain(CppPlatform, Target); } else { return new VCToolChain(CppPlatform, Target); } } /// /// 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 override void GetExternalBuildMetadata(FileReference ProjectFile, StringBuilder Metadata) { base.GetExternalBuildMetadata(ProjectFile, Metadata); if(ProjectFile != null) { Metadata.AppendLine("ICON: {0}", GetApplicationIcon(ProjectFile)); } } /// /// Deploys the given target /// /// Receipt for the target being deployed public override void Deploy(TargetReceipt Receipt) { } } class WindowsPlatformSDK : UEBuildPlatformSDK { protected override SDKStatus HasRequiredManualSDKInternal() { return SDKStatus.Valid; } } class WindowsPlatformFactory : UEBuildPlatformFactory { public override UnrealTargetPlatform TargetPlatform { get { return UnrealTargetPlatform.Win64; } } /// /// Register the platform with the UEBuildPlatform class /// public override void RegisterBuildPlatforms() { WindowsPlatformSDK SDK = new WindowsPlatformSDK(); SDK.ManageAndValidateSDK(); // Register this build platform for both Win64 and Win32 Log.TraceVerbose(" Registering for {0}", UnrealTargetPlatform.Win64.ToString()); UEBuildPlatform.RegisterBuildPlatform(new WindowsPlatform(UnrealTargetPlatform.Win64, CppPlatform.Win64, SDK)); UEBuildPlatform.RegisterPlatformWithGroup(UnrealTargetPlatform.Win64, UnrealPlatformGroup.Windows); UEBuildPlatform.RegisterPlatformWithGroup(UnrealTargetPlatform.Win64, UnrealPlatformGroup.Microsoft); Log.TraceVerbose(" Registering for {0}", UnrealTargetPlatform.Win32.ToString()); UEBuildPlatform.RegisterBuildPlatform(new WindowsPlatform(UnrealTargetPlatform.Win32, CppPlatform.Win32, SDK)); UEBuildPlatform.RegisterPlatformWithGroup(UnrealTargetPlatform.Win32, UnrealPlatformGroup.Windows); UEBuildPlatform.RegisterPlatformWithGroup(UnrealTargetPlatform.Win32, UnrealPlatformGroup.Microsoft); } } }