// 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);
}
}
}