// Copyright 1998-2017 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; 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, /// /// Visual Studio 2013 (Visual C++ 12.0) /// [Obsolete("UE4 does not support building Visual Studio 2013 targets from the 4.16 release onwards.")] VisualStudio2013, /// /// Visual Studio 2015 (Visual C++ 14.0) /// VisualStudio2015, /// /// Visual Studio 2017 (Visual C++ 15.0) /// VisualStudio2017, } /// /// 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")] public WindowsCompiler Compiler = WindowsCompiler.Default; /// /// 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 project's name. /// [ConfigFile(ConfigHierarchyType.Game, "/Script/EngineSettings.GeneralProjectSettings", "ProjectName")] public string ProductName; /// 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 || Compiler == WindowsCompiler.VisualStudio2017; } } /// /// 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.VisualStudio2015: return "2015"; case WindowsCompiler.VisualStudio2017: 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 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 bool bNeedsLegacyStdioDefinitionsLib { get { return Inner.bNeedsLegacyStdioDefinitionsLib; } } public string GetVisualStudioCompilerVersionName() { return Inner.GetVisualStudioCompilerVersionName(); } #if !__MonoCS__ #pragma warning restore CS1591 #endif #endregion } class WindowsPlatform : UEBuildPlatform { /// /// True if we should use Clang/LLVM instead of MSVC to compile code on Windows platform /// public static readonly bool bCompileWithClang = false; /// /// When using Clang, enabling enables the MSVC-like "clang-cl" wrapper, otherwise we pass arguments to Clang directly /// public static readonly bool bUseVCCompilerArgs = true; /// /// True if we should use the Clang linker (LLD) when bCompileWithClang is enabled, otherwise we use the MSVC linker /// public static readonly bool bAllowClangLinker = bCompileWithClang && false; /// /// True if we should use the Intel Compiler instead of MSVC to compile code on Windows platform /// public static readonly bool bCompileWithICL = 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 = bCompileWithICL && true; /// /// Whether to compile against the Windows 10 SDK, instead of the Windows 8.1 SDK. This requires the Visual Studio 2015 /// compiler or later, and the Windows 10 SDK must be installed. The application will require at least Windows 8.x to run. /// @todo UWP: Expose this to be enabled more easily for building Windows 10 desktop apps /// public static readonly bool bUseWindowsSDK10 = false; /// /// True if we allow using addresses larger than 2GB on 32 bit builds /// public static readonly bool bBuildLargeAddressAwareBinary = 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(); } /// /// Validate a target's settings /// public override void ValidateTarget(TargetRules Target) { Target.bCompileNvCloth = true; // Disable Simplygon support if compiling against the NULL RHI. if (Target.GlobalDefinitions.Contains("USE_NULL_RHI=1")) { Target.bCompileSimplygon = false; Target.bCompileSimplygonSSF = false; } // Set the compiler version if necessary if (Target.WindowsPlatform.Compiler == WindowsCompiler.Default) { Target.WindowsPlatform.Compiler = GetDefaultCompiler(); } // Override PCH settings if (bCompileWithClang) { // @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) if (WindowsPlatform.bUseVCCompilerArgs) { Target.bUsePCHFiles = false; } } if (bCompileWithICL) { Target.bUseSharedPCHs = false; if (WindowsPlatform.bUseVCCompilerArgs) { Target.bUsePCHFiles = false; } } // E&C support. if (Target.bSupportEditAndContinue && Target.Configuration == UnrealTargetConfiguration.Debug) { Target.bUseIncrementalLinking = true; } // Incremental linking. if (Target.bUseIncrementalLinking && !Target.bDisableDebugInfo) { Target.bUsePDBFiles = 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() { // If there's no specific compiler set, try to pick the matching compiler for the selected IDE object ProjectFormatObject; if (XmlConfig.TryGetValue(typeof(VCProjectFileGenerator), "Version", out ProjectFormatObject)) { VCProjectFileFormat ProjectFormat = (VCProjectFileFormat)ProjectFormatObject; if (ProjectFormat == VCProjectFileFormat.VisualStudio2017) { return WindowsCompiler.VisualStudio2017; } else if (ProjectFormat == VCProjectFileFormat.VisualStudio2015) { return WindowsCompiler.VisualStudio2015; } } // Second, default based on what's installed, test for 2015 first DirectoryReference VCInstallDir; if (TryGetVCInstallDir(WindowsCompiler.VisualStudio2015, out VCInstallDir)) { return WindowsCompiler.VisualStudio2015; } if (TryGetVCInstallDir(WindowsCompiler.VisualStudio2017, out VCInstallDir)) { return WindowsCompiler.VisualStudio2017; } // If we do have a Visual Studio installation, but we're missing just the C++ parts, warn about that. DirectoryReference VSInstallDir; if (TryGetVSInstallDir(WindowsCompiler.VisualStudio2015, out VSInstallDir)) { Log.TraceWarning("Visual Studio 2015 is installed, but is missing the C++ toolchain. Please verify that \"Common Tools for Visual C++ 2015\" are selected from the Visual Studio 2015 installation options."); } else 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 { Log.TraceWarning("No Visual C++ installation was found. Please download and install Visual Studio 2015 with C++ components."); } // Finally, default to VS2015 anyway return WindowsCompiler.VisualStudio2015; } /// /// 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: return "Visual Studio 2015"; case WindowsCompiler.VisualStudio2017: return "Visual Studio 2017"; default: return Compiler.ToString(); } } /// /// 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. /// 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; } switch (Compiler) { case WindowsCompiler.VisualStudio2015: return TryReadInstallDirRegistryKey32("Microsoft\\VisualStudio\\SxS\\VS7", "14.0", out InstallDir); case WindowsCompiler.VisualStudio2017: return TryReadInstallDirRegistryKey32("Microsoft\\VisualStudio\\SxS\\VS7", "15.0", out InstallDir); default: throw new BuildException("Invalid compiler version ({0})", Compiler); } } /// /// Read the Visual C++ install directory for the given version. /// /// Version of the toolchain to look for. /// On success, the directory that Visual C++ is installed to. /// True if the directory was found, false otherwise. public static bool TryGetVCInstallDir(WindowsCompiler Compiler, out DirectoryReference InstallDir) { if (BuildHostPlatform.Current.Platform != UnrealTargetPlatform.Win64 && BuildHostPlatform.Current.Platform != UnrealTargetPlatform.Win32) { InstallDir = null; return false; } if (Compiler == WindowsCompiler.VisualStudio2015) { return TryReadInstallDirRegistryKey32("Microsoft\\VisualStudio\\SxS\\VC7", "14.0", out InstallDir); } else if (Compiler == WindowsCompiler.VisualStudio2017) { // VS15Preview installs the compiler under the IDE directory, and does not register it as a standalone component. Check just in case this changes // for compat in future since it's more specific. if (TryReadInstallDirRegistryKey32("Microsoft\\VisualStudio\\SxS\\VC7", "15.0", out InstallDir)) { return true; } // Otherwise just check under the VS folder... DirectoryReference VSInstallDir; if (TryGetVSInstallDir(Compiler, out VSInstallDir)) { FileReference VersionPath = FileReference.Combine(VSInstallDir, "VC", "Auxiliary", "Build", "Microsoft.VCToolsVersion.default.txt"); if (FileReference.Exists(VersionPath)) { InstallDir = VersionPath.Directory.ParentDirectory.ParentDirectory; return true; } } return false; } else { throw new BuildException("Invalid compiler version ({0})", Compiler); } } /// /// 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; } } /// /// If this platform can be compiled with SN-DBS /// public override bool CanUseSNDBS() { // Check that SN-DBS is available string SCERootPath = Environment.GetEnvironmentVariable("SCE_ROOT_DIR"); if (!String.IsNullOrEmpty(SCERootPath)) { string SNDBSPath = Path.Combine(SCERootPath, "common", "sn-dbs", "bin", "dbsbuild.exe"); bool bIsSNDBSAvailable = File.Exists(SNDBSPath); return bIsSNDBSAvailable; } else { return false; } } /// /// 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"; case UEBuildBinaryType.Object: return ".obj"; case UEBuildBinaryType.PrecompiledHeader: return ".pch"; } return base.GetBinaryExtension(InBinaryType); } /// /// Get the extension to use for debug info for the given binary type /// /// The target being built /// The binary type being built /// string The debug info extension (i.e. 'pdb') public override string GetDebugInfoExtension(ReadOnlyTargetRules Target, UEBuildBinaryType InBinaryType) { switch (InBinaryType) { case UEBuildBinaryType.DynamicLinkLibrary: case UEBuildBinaryType.Executable: return ".pdb"; } return ""; } /// /// Whether the editor should be built for this platform or not /// /// The UnrealTargetPlatform being built /// The UnrealTargetConfiguration being built /// bool true if the editor should be built, false if not public override bool ShouldNotBuildEditor(UnrealTargetPlatform InPlatform, UnrealTargetConfiguration InConfiguration) { return false; } public override bool BuildRequiresCookedData(UnrealTargetPlatform InPlatform, UnrealTargetConfiguration InConfiguration) { return false; } 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) { } /// /// Return whether this platform has uniquely named binaries across multiple games /// public override bool HasUniqueBinaries() { // Windows applications have many shared binaries between games return false; } /// /// 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.Definitions.Add("D3D12_PROFILING_ENABLED=1"); Rules.Definitions.Add("PROFILE"); Rules.PublicAdditionalLibraries.Add("WinPixEventRuntime.lib"); Rules.PublicDelayLoadDLLs.Add("WinPixEventRuntime.dll"); Rules.RuntimeDependencies.Add(new RuntimeDependency("$(EngineDir)/Binaries/ThirdParty/Windows/DirectX/x64/WinPixEventRuntime.dll")); } else { Rules.Definitions.Add("D3D12_PROFILING_ENABLED=0"); } // To enable platform specific D3D12 RHI Types Rules.PrivateIncludePaths.Add("Runtime/Windows/D3D12RHI/Private/Windows"); } // 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"); if (WindowsPlatform.bUseWindowsSDK10) { // Windows 8 or higher required CompileEnvironment.Definitions.Add("_WIN32_WINNT=0x0602"); CompileEnvironment.Definitions.Add("WINVER=0x0602"); } else { // Windows 7 or higher required CompileEnvironment.Definitions.Add("_WIN32_WINNT=0x0601"); CompileEnvironment.Definitions.Add("WINVER=0x0601"); } CompileEnvironment.Definitions.Add("PLATFORM_WINDOWS=1"); CompileEnvironment.Definitions.Add("DEPTH_32_BIT_CONVERSION=0"); FileReference MorpheusShaderPath = FileReference.Combine(UnrealBuildTool.EngineDirectory, "Shaders", "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 (WindowsPlatform.bCompileWithICL) { var 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(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"; } if (Target.Type != TargetType.Editor) { if (!string.IsNullOrEmpty(Target.WindowsPlatform.CompanyName)) { CompileEnvironment.Definitions.Add(String.Format("PROJECT_COMPANY_NAME={0}", SanitizeMacroValue(Target.WindowsPlatform.CompanyName))); } if (!string.IsNullOrEmpty(Target.WindowsPlatform.CopyrightNotice)) { CompileEnvironment.Definitions.Add(String.Format("PROJECT_COPYRIGHT_STRING={0}", SanitizeMacroValue(Target.WindowsPlatform.CopyrightNotice))); } if (!string.IsNullOrEmpty(Target.WindowsPlatform.ProductName)) { CompileEnvironment.Definitions.Add(String.Format("PROJECT_PRODUCT_NAME={0}", SanitizeMacroValue(Target.WindowsPlatform.ProductName))); } if (Target.ProjectFile != null) { CompileEnvironment.Definitions.Add(String.Format("PROJECT_PRODUCT_IDENTIFIER={0}", SanitizeMacroValue(Target.ProjectFile.GetFileNameWithoutExtension()))); } } // Set up default stack size ConfigHierarchy EngineIni = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(Target.ProjectFile), UnrealTargetPlatform.Win64); String TargetSettingsIniPath = "/Script/WindowsTargetPlatform.WindowsTargetSettings"; int IniDefaultStackSize = 0; String StackSizeName = Target.Type == TargetType.Editor ? "DefaultStackSizeEditor" : "DefaultStackSize"; if (EngineIni.GetInt32(TargetSettingsIniPath, StackSizeName, out IniDefaultStackSize)) { LinkEnvironment.DefaultStackSize = IniDefaultStackSize; } int IniDefaultStackSizeCommit = 0; String StackSizeCommitName = Target.Type == TargetType.Editor ? "DefaultStackSizeCommitEditor" : "DefaultStackSizeCommit"; if (EngineIni.GetInt32(TargetSettingsIniPath, StackSizeCommitName, out IniDefaultStackSizeCommit)) { LinkEnvironment.DefaultStackSizeCommit = IniDefaultStackSizeCommit; } } /// /// Macros passed via the command line have their quotes stripped, and are tokenized before being re-stringized by the compiler. This conversion /// back and forth is normally ok, but certain characters such as single quotes must always be paired. Remove any such characters here. /// /// The macro value /// The sanitized value static string SanitizeMacroValue(string Value) { StringBuilder Result = new StringBuilder(Value.Length); for(int Idx = 0; Idx < Value.Length; Idx++) { if(Value[Idx] != '\'' && Value[Idx] != '\"') { Result.Append(Value[Idx]); } } return Result.ToString(); } /// /// 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) { return new VCToolChain(CppPlatform, Target.WindowsPlatform.Compiler); } /// /// Deploys the given target /// /// Information about the target being deployed public override void Deploy(UEBuildDeployTarget Target) { new BaseWindowsDeploy().PrepTargetForDeployment(Target); } } class WindowsPlatformSDK : UEBuildPlatformSDK { protected override SDKStatus HasRequiredManualSDKInternal() { return SDKStatus.Valid; } } class WindowsPlatformFactory : UEBuildPlatformFactory { protected override UnrealTargetPlatform TargetPlatform { get { return UnrealTargetPlatform.Win64; } } /// /// Register the platform with the UEBuildPlatform class /// protected override void RegisterBuildPlatforms(SDKOutputLevel OutputLevel) { WindowsPlatformSDK SDK = new WindowsPlatformSDK(); SDK.ManageAndValidateSDK(OutputLevel); // 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); } } }