Enabled the disabled optimization flags with whole program optimization flag where the compilation speed doesn't seem to be affected at all, but binary size is slightly smaller.
1163 lines
49 KiB
C#
1163 lines
49 KiB
C#
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Xml;
|
|
using Flax.Build.Graph;
|
|
using Flax.Build.NativeCpp;
|
|
using Flax.Build.Projects.VisualStudio;
|
|
|
|
// ReSharper disable InconsistentNaming
|
|
|
|
namespace Flax.Build.Platforms
|
|
{
|
|
/// <summary>
|
|
/// The Microsoft Windows base toolchain implementation.
|
|
/// </summary>
|
|
/// <seealso cref="Toolchain" />
|
|
public abstract class WindowsToolchainBase : Toolchain
|
|
{
|
|
/// <summary>
|
|
/// The VC tools root path.
|
|
/// </summary>
|
|
protected readonly string _vcToolPath;
|
|
|
|
/// <summary>
|
|
/// The compiler path.
|
|
/// </summary>
|
|
protected readonly string _compilerPath;
|
|
|
|
/// <summary>
|
|
/// The resource compiler path.
|
|
/// </summary>
|
|
protected readonly string _resourceCompilerPath;
|
|
|
|
/// <summary>
|
|
/// The linker path.
|
|
/// </summary>
|
|
protected readonly string _linkerPath;
|
|
|
|
/// <summary>
|
|
/// The library tool path.
|
|
/// </summary>
|
|
protected readonly string _libToolPath;
|
|
|
|
/// <summary>
|
|
/// The xdcmake tool path.
|
|
/// </summary>
|
|
protected readonly string _xdcmakePath;
|
|
|
|
/// <summary>
|
|
/// The makepri tool path.
|
|
/// </summary>
|
|
protected readonly string _makepriPath;
|
|
|
|
/// <summary>
|
|
/// Gets the platform toolset.
|
|
/// </summary>
|
|
public WindowsPlatformToolset Toolset { get; }
|
|
|
|
/// <summary>
|
|
/// Gets the target platform SDK.
|
|
/// </summary>
|
|
public WindowsPlatformSDK SDK { get; }
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="WindowsToolchainBase"/> class.
|
|
/// </summary>
|
|
/// <param name="platform">The platform.</param>
|
|
/// <param name="architecture">The target architecture.</param>
|
|
/// <param name="toolsetVer">The target platform toolset version.</param>
|
|
/// <param name="sdkVer">The target platform SDK version.</param>
|
|
protected WindowsToolchainBase(WindowsPlatformBase platform, TargetArchitecture architecture, WindowsPlatformToolset toolsetVer, WindowsPlatformSDK sdkVer)
|
|
: base(platform, architecture)
|
|
{
|
|
var toolsets = WindowsPlatformBase.GetToolsets();
|
|
var sdks = WindowsPlatformBase.GetSDKs();
|
|
|
|
// Pick the overriden toolset
|
|
if (Configuration.Compiler != null)
|
|
{
|
|
if (Enum.TryParse(Configuration.Compiler, out WindowsPlatformToolset compiler))
|
|
toolsetVer = compiler;
|
|
}
|
|
|
|
// Pick the newest installed Visual Studio version if using the default toolset
|
|
if (toolsetVer == WindowsPlatformToolset.Default)
|
|
{
|
|
if (VisualStudioInstance.HasIDE(VisualStudioVersion.VisualStudio2022))
|
|
{
|
|
if (toolsets.Keys.Contains(WindowsPlatformToolset.v144))
|
|
{
|
|
toolsetVer = WindowsPlatformToolset.v144;
|
|
}
|
|
else
|
|
{
|
|
toolsetVer = WindowsPlatformToolset.v143;
|
|
}
|
|
}
|
|
else if (VisualStudioInstance.HasIDE(VisualStudioVersion.VisualStudio2019))
|
|
{
|
|
toolsetVer = WindowsPlatformToolset.v142;
|
|
}
|
|
else if (VisualStudioInstance.HasIDE(VisualStudioVersion.VisualStudio2017))
|
|
{
|
|
toolsetVer = WindowsPlatformToolset.v141;
|
|
}
|
|
else
|
|
{
|
|
toolsetVer = WindowsPlatformToolset.v140;
|
|
}
|
|
}
|
|
// Pick the latest toolset
|
|
else if (toolsetVer == WindowsPlatformToolset.Latest)
|
|
{
|
|
toolsetVer = toolsets.Keys.Max();
|
|
}
|
|
|
|
// Pick the latest SDK
|
|
if (sdkVer == WindowsPlatformSDK.Latest)
|
|
{
|
|
sdkVer = sdks.Keys.Max();
|
|
}
|
|
|
|
// Get tools
|
|
Toolset = toolsetVer;
|
|
SDK = sdkVer;
|
|
if (!toolsets.ContainsKey(Toolset))
|
|
throw new Exception(string.Format("Missing toolset {0} for platform Windows", Toolset));
|
|
if (!sdks.ContainsKey(SDK))
|
|
throw new Exception(string.Format("Missing SDK {0} for platform Windows", SDK));
|
|
|
|
// Get the tools paths
|
|
string vcToolPath;
|
|
if (Architecture == TargetArchitecture.x64)
|
|
vcToolPath = WindowsPlatformBase.GetVCToolPath64(Toolset);
|
|
else
|
|
vcToolPath = WindowsPlatformBase.GetVCToolPath32(Toolset);
|
|
_vcToolPath = vcToolPath;
|
|
_compilerPath = Path.Combine(vcToolPath, "cl.exe");
|
|
_linkerPath = Path.Combine(vcToolPath, "link.exe");
|
|
_libToolPath = Path.Combine(vcToolPath, "lib.exe");
|
|
_xdcmakePath = Path.Combine(vcToolPath, "xdcmake.exe");
|
|
|
|
// Add Visual C++ toolset include and library paths
|
|
var vcToolChainDir = toolsets[Toolset];
|
|
SystemIncludePaths.Add(Path.Combine(vcToolChainDir, "include"));
|
|
switch (Toolset)
|
|
{
|
|
case WindowsPlatformToolset.v140:
|
|
{
|
|
switch (Architecture)
|
|
{
|
|
case TargetArchitecture.AnyCPU: break;
|
|
case TargetArchitecture.ARM:
|
|
SystemLibraryPaths.Add(Path.Combine(vcToolChainDir, "lib", "arm"));
|
|
break;
|
|
case TargetArchitecture.ARM64:
|
|
SystemLibraryPaths.Add(Path.Combine(vcToolChainDir, "lib", "arm64"));
|
|
break;
|
|
case TargetArchitecture.x86:
|
|
SystemLibraryPaths.Add(Path.Combine(vcToolChainDir, "lib"));
|
|
break;
|
|
case TargetArchitecture.x64:
|
|
SystemLibraryPaths.Add(Path.Combine(vcToolChainDir, "lib", "amd64"));
|
|
break;
|
|
default: throw new InvalidArchitectureException(architecture);
|
|
}
|
|
|
|
// When using Visual Studio 2015 toolset and using pre-Windows 10 SDK, find a Windows 10 SDK and add the UCRT include paths
|
|
if (SDK == WindowsPlatformSDK.v8_1)
|
|
{
|
|
var sdk = sdks.FirstOrDefault(x => x.Key != WindowsPlatformSDK.v8_1);
|
|
if (sdk.Value == null)
|
|
{
|
|
throw new Exception("Combination of Windows Toolset v140 and Windows SDK 8.1 requires the Universal CRT to be installed.");
|
|
}
|
|
|
|
var sdkVersionName = WindowsPlatformBase.GetSDKVersion(sdk.Key).ToString();
|
|
string includeRootDir = Path.Combine(sdk.Value, "include", sdkVersionName);
|
|
SystemIncludePaths.Add(Path.Combine(includeRootDir, "ucrt"));
|
|
|
|
string libraryRootDir = Path.Combine(sdk.Value, "lib", sdkVersionName);
|
|
switch (Architecture)
|
|
{
|
|
case TargetArchitecture.AnyCPU: break;
|
|
case TargetArchitecture.ARM:
|
|
SystemLibraryPaths.Add(Path.Combine(libraryRootDir, "ucrt", "arm"));
|
|
break;
|
|
case TargetArchitecture.ARM64:
|
|
SystemLibraryPaths.Add(Path.Combine(libraryRootDir, "ucrt", "arm64"));
|
|
break;
|
|
case TargetArchitecture.x86:
|
|
SystemLibraryPaths.Add(Path.Combine(libraryRootDir, "ucrt", "x86"));
|
|
break;
|
|
case TargetArchitecture.x64:
|
|
SystemLibraryPaths.Add(Path.Combine(libraryRootDir, "ucrt", "x64"));
|
|
break;
|
|
default: throw new InvalidArchitectureException(architecture);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case WindowsPlatformToolset.v141:
|
|
case WindowsPlatformToolset.v142:
|
|
case WindowsPlatformToolset.v143:
|
|
case WindowsPlatformToolset.v144:
|
|
{
|
|
switch (Architecture)
|
|
{
|
|
case TargetArchitecture.AnyCPU: break;
|
|
case TargetArchitecture.ARM:
|
|
SystemLibraryPaths.Add(Path.Combine(vcToolChainDir, "lib", "arm"));
|
|
break;
|
|
case TargetArchitecture.ARM64:
|
|
SystemLibraryPaths.Add(Path.Combine(vcToolChainDir, "lib", "arm64"));
|
|
break;
|
|
case TargetArchitecture.x86:
|
|
SystemLibraryPaths.Add(Path.Combine(vcToolChainDir, "lib", "x86"));
|
|
break;
|
|
case TargetArchitecture.x64:
|
|
SystemLibraryPaths.Add(Path.Combine(vcToolChainDir, "lib", "x64"));
|
|
break;
|
|
default: throw new InvalidArchitectureException(architecture);
|
|
}
|
|
break;
|
|
}
|
|
default: throw new ArgumentOutOfRangeException();
|
|
}
|
|
|
|
// Add Windows SDK include and library paths
|
|
var windowsSdkDir = sdks[SDK];
|
|
switch (SDK)
|
|
{
|
|
case WindowsPlatformSDK.v8_1:
|
|
{
|
|
string includeRootDir = Path.Combine(windowsSdkDir, "include");
|
|
SystemIncludePaths.Add(Path.Combine(includeRootDir, "shared"));
|
|
SystemIncludePaths.Add(Path.Combine(includeRootDir, "um"));
|
|
SystemIncludePaths.Add(Path.Combine(includeRootDir, "winrt"));
|
|
SystemIncludePaths.Add(Path.Combine(includeRootDir, "ucrt"));
|
|
|
|
string libraryRootDir = Path.Combine(windowsSdkDir, "lib", "winv6.3");
|
|
switch (Architecture)
|
|
{
|
|
case TargetArchitecture.AnyCPU: break;
|
|
case TargetArchitecture.ARM:
|
|
{
|
|
SystemLibraryPaths.Add(Path.Combine(libraryRootDir, "um", "arm"));
|
|
break;
|
|
}
|
|
case TargetArchitecture.ARM64:
|
|
{
|
|
SystemLibraryPaths.Add(Path.Combine(libraryRootDir, "um", "arm64"));
|
|
break;
|
|
}
|
|
case TargetArchitecture.x86:
|
|
{
|
|
SystemLibraryPaths.Add(Path.Combine(libraryRootDir, "um", "x86"));
|
|
SystemLibraryPaths.Add(Path.Combine(libraryRootDir, "ucrt", "x86"));
|
|
var binRootDir = Path.Combine(windowsSdkDir, "bin", "x86");
|
|
_resourceCompilerPath = Path.Combine(binRootDir, "rc.exe");
|
|
_makepriPath = Path.Combine(binRootDir, "makepri.exe");
|
|
break;
|
|
}
|
|
case TargetArchitecture.x64:
|
|
{
|
|
SystemLibraryPaths.Add(Path.Combine(libraryRootDir, "um", "x64"));
|
|
SystemLibraryPaths.Add(Path.Combine(libraryRootDir, "ucrt", "x64"));
|
|
var binRootDir = Path.Combine(windowsSdkDir, "bin", "x64");
|
|
_resourceCompilerPath = Path.Combine(binRootDir, "rc.exe");
|
|
_makepriPath = Path.Combine(binRootDir, "makepri.exe");
|
|
break;
|
|
}
|
|
default: throw new InvalidArchitectureException(architecture);
|
|
}
|
|
break;
|
|
}
|
|
case WindowsPlatformSDK.v10_0_10240_0:
|
|
case WindowsPlatformSDK.v10_0_10586_0:
|
|
case WindowsPlatformSDK.v10_0_14393_0:
|
|
case WindowsPlatformSDK.v10_0_15063_0:
|
|
case WindowsPlatformSDK.v10_0_16299_0:
|
|
case WindowsPlatformSDK.v10_0_17134_0:
|
|
case WindowsPlatformSDK.v10_0_17763_0:
|
|
case WindowsPlatformSDK.v10_0_18362_0:
|
|
case WindowsPlatformSDK.v10_0_19041_0:
|
|
case WindowsPlatformSDK.v10_0_20348_0:
|
|
case WindowsPlatformSDK.v10_0_22000_0:
|
|
case WindowsPlatformSDK.v10_0_22621_0:
|
|
{
|
|
var sdkVersionName = WindowsPlatformBase.GetSDKVersion(SDK).ToString();
|
|
string includeRootDir = Path.Combine(windowsSdkDir, "include", sdkVersionName);
|
|
SystemIncludePaths.Add(Path.Combine(includeRootDir, "ucrt"));
|
|
SystemIncludePaths.Add(Path.Combine(includeRootDir, "shared"));
|
|
SystemIncludePaths.Add(Path.Combine(includeRootDir, "um"));
|
|
SystemIncludePaths.Add(Path.Combine(includeRootDir, "winrt"));
|
|
|
|
string libraryRootDir = Path.Combine(windowsSdkDir, "lib", sdkVersionName);
|
|
switch (Architecture)
|
|
{
|
|
case TargetArchitecture.AnyCPU: break;
|
|
case TargetArchitecture.ARM:
|
|
{
|
|
SystemLibraryPaths.Add(Path.Combine(libraryRootDir, "ucrt", "arm"));
|
|
SystemLibraryPaths.Add(Path.Combine(libraryRootDir, "um", "arm"));
|
|
break;
|
|
}
|
|
case TargetArchitecture.ARM64:
|
|
{
|
|
SystemLibraryPaths.Add(Path.Combine(libraryRootDir, "ucrt", "arm64"));
|
|
SystemLibraryPaths.Add(Path.Combine(libraryRootDir, "um", "arm64"));
|
|
break;
|
|
}
|
|
case TargetArchitecture.x86:
|
|
{
|
|
SystemLibraryPaths.Add(Path.Combine(libraryRootDir, "ucrt", "x86"));
|
|
SystemLibraryPaths.Add(Path.Combine(libraryRootDir, "um", "x86"));
|
|
var binRootDir = Path.Combine(windowsSdkDir, "bin", sdkVersionName, "x86");
|
|
_resourceCompilerPath = Path.Combine(binRootDir, "rc.exe");
|
|
_makepriPath = Path.Combine(binRootDir, "makepri.exe");
|
|
break;
|
|
}
|
|
case TargetArchitecture.x64:
|
|
{
|
|
SystemLibraryPaths.Add(Path.Combine(libraryRootDir, "ucrt", "x64"));
|
|
SystemLibraryPaths.Add(Path.Combine(libraryRootDir, "um", "x64"));
|
|
var binRootDir = Path.Combine(windowsSdkDir, "bin", sdkVersionName, "x64");
|
|
_resourceCompilerPath = Path.Combine(binRootDir, "rc.exe");
|
|
_makepriPath = Path.Combine(binRootDir, "makepri.exe");
|
|
break;
|
|
}
|
|
default: throw new InvalidArchitectureException(architecture);
|
|
}
|
|
break;
|
|
}
|
|
default: throw new ArgumentOutOfRangeException(nameof(SDK));
|
|
}
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public override bool UseImportLibraryWhenLinking => true;
|
|
|
|
/// <inheritdoc />
|
|
public override bool GeneratesImportLibraryWhenLinking => true;
|
|
|
|
/// <inheritdoc />
|
|
public override string DllExport => "__declspec(dllexport)";
|
|
|
|
/// <inheritdoc />
|
|
public override string DllImport => "__declspec(dllimport)";
|
|
|
|
/// <inheritdoc />
|
|
public override TargetCompiler Compiler => TargetCompiler.MSVC;
|
|
|
|
/// <inheritdoc />
|
|
public override void LogInfo()
|
|
{
|
|
var sdkPath = WindowsPlatformBase.GetSDKs()[SDK];
|
|
Log.Info(string.Format("Using Windows Toolset {0} ({1})", Toolset, sdkPath));
|
|
Log.Info(string.Format("Using Windows SDK {0} ({1})", WindowsPlatformBase.GetSDKVersion(SDK), _vcToolPath));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds the include path to the command line arguments.
|
|
/// </summary>
|
|
/// <param name="args">The arguments.</param>
|
|
/// <param name="path">The include path.</param>
|
|
protected static void AddIncludePath(List<string> args, string path)
|
|
{
|
|
if (path.Contains(' '))
|
|
args.Add(string.Format("/I\"{0}\"", path));
|
|
else
|
|
args.Add(string.Format("/I{0}", path));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the C++/CX metadata file directory.
|
|
/// </summary>
|
|
/// <returns>The folder path or null if not found.</returns>
|
|
protected string GetCppCXMetadataDirectory()
|
|
{
|
|
var toolsets = WindowsPlatformBase.GetToolsets();
|
|
var vcToolChainDir = toolsets[Toolset];
|
|
switch (Toolset)
|
|
{
|
|
case WindowsPlatformToolset.v144:
|
|
case WindowsPlatformToolset.v143:
|
|
case WindowsPlatformToolset.v142:
|
|
case WindowsPlatformToolset.v141: return Path.Combine(vcToolChainDir, "lib", "x86", "store", "references");
|
|
case WindowsPlatformToolset.v140: return Path.Combine(vcToolChainDir, "lib", "store", "references");
|
|
default: return null;
|
|
}
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public override void SetupEnvironment(BuildOptions options)
|
|
{
|
|
base.SetupEnvironment(options);
|
|
|
|
options.CompileEnv.PreprocessorDefinitions.Add("PLATFORM_WIN32");
|
|
options.CompileEnv.PreprocessorDefinitions.Add("WIN32");
|
|
options.CompileEnv.PreprocessorDefinitions.Add("_CRT_SECURE_NO_DEPRECATE");
|
|
options.CompileEnv.PreprocessorDefinitions.Add("_CRT_SECURE_NO_WARNINGS");
|
|
options.CompileEnv.PreprocessorDefinitions.Add("_WINDOWS");
|
|
if (Architecture == TargetArchitecture.x64)
|
|
options.CompileEnv.PreprocessorDefinitions.Add("WIN64");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Setups the C++ files compilation arguments.
|
|
/// </summary>
|
|
/// <param name="graph">The graph.</param>
|
|
/// <param name="options">The options.</param>
|
|
/// <param name="args">The arguments.</param>
|
|
protected virtual void SetupCompileCppFilesArgs(TaskGraph graph, BuildOptions options, List<string> args)
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Setups the linking files arguments.
|
|
/// </summary>
|
|
/// <param name="graph">The graph.</param>
|
|
/// <param name="options">The options.</param>
|
|
/// <param name="args">The arguments.</param>
|
|
protected virtual void SetupLinkFilesArgs(TaskGraph graph, BuildOptions options, List<string> args)
|
|
{
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public override CompileOutput CompileCppFiles(TaskGraph graph, BuildOptions options, List<string> sourceFiles, string outputPath)
|
|
{
|
|
var compileEnvironment = options.CompileEnv;
|
|
var output = new CompileOutput();
|
|
|
|
// Setup arguments shared by all source files
|
|
var commonArgs = new List<string>();
|
|
commonArgs.AddRange(options.CompileEnv.CustomArgs);
|
|
SetupCompileCppFilesArgs(graph, options, commonArgs);
|
|
var useSeparatePdb = true; //compileEnvironment.PrecompiledHeaderUsage == PrecompiledHeaderFileUsage.None;
|
|
{
|
|
// Suppress Startup Banner
|
|
commonArgs.Add("/nologo");
|
|
|
|
// Compile Without Linking
|
|
commonArgs.Add("/c");
|
|
|
|
// C++ version
|
|
switch (compileEnvironment.CppVersion)
|
|
{
|
|
case CppVersion.Cpp14:
|
|
commonArgs.Add("/std:c++14");
|
|
break;
|
|
case CppVersion.Cpp17:
|
|
commonArgs.Add("/std:c++17");
|
|
break;
|
|
case CppVersion.Cpp20:
|
|
commonArgs.Add("/std:c++20");
|
|
break;
|
|
case CppVersion.Latest:
|
|
commonArgs.Add("/std:c++latest");
|
|
break;
|
|
}
|
|
commonArgs.Add("/Zc:__cplusplus");
|
|
|
|
// Generate Intrinsic Functions
|
|
if (compileEnvironment.IntrinsicFunctions)
|
|
commonArgs.Add("/Oi");
|
|
|
|
// Enable Function-Level Linking
|
|
if (compileEnvironment.FunctionLevelLinking)
|
|
commonArgs.Add("/Gy");
|
|
else
|
|
commonArgs.Add("/Gy-");
|
|
|
|
// List Include Files
|
|
//commonArgs.Add("/showIncludes");
|
|
|
|
// Code Analysis
|
|
commonArgs.Add("/analyze-");
|
|
|
|
// Remove unreferenced COMDAT
|
|
commonArgs.Add("/Zc:inline");
|
|
|
|
// Run-Time Error Checks
|
|
if (compileEnvironment.RuntimeChecks && !compileEnvironment.CompileAsWinRT)
|
|
commonArgs.Add("/RTC1");
|
|
|
|
// Inline Function Expansion
|
|
if (compileEnvironment.Inlining)
|
|
commonArgs.Add("/Ob2");
|
|
|
|
if (compileEnvironment.DebugInformation)
|
|
{
|
|
// Debug Information Format
|
|
if (useSeparatePdb)
|
|
commonArgs.Add("/Zi");
|
|
else
|
|
commonArgs.Add("/Z7");
|
|
|
|
// Enhance Optimized Debugging
|
|
commonArgs.Add("/Zo");
|
|
}
|
|
|
|
// Favor Small Code, Favor Fast Code
|
|
if (compileEnvironment.FavorSizeOrSpeed == FavorSizeOrSpeed.FastCode)
|
|
commonArgs.Add("/Ot");
|
|
else if (compileEnvironment.FavorSizeOrSpeed == FavorSizeOrSpeed.SmallCode)
|
|
commonArgs.Add("/Os");
|
|
if (compileEnvironment.Optimization)
|
|
{
|
|
// Enable Most Speed Optimizations
|
|
// Commented out due to /Og causing slow build times without /GL in development builds
|
|
//commonArgs.Add("/Ox");
|
|
|
|
// Generate Intrinsic Functions
|
|
commonArgs.Add("/Oi");
|
|
|
|
// Frame-Pointer Omission
|
|
commonArgs.Add("/Oy");
|
|
|
|
if (compileEnvironment.WholeProgramOptimization)
|
|
{
|
|
// Enable Most Speed Optimizations
|
|
commonArgs.Add("/Ox");
|
|
|
|
// Whole Program Optimization
|
|
commonArgs.Add("/GL");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Disable compiler optimizations (Debug)
|
|
commonArgs.Add("/Od");
|
|
|
|
// Frame-Pointer Omission
|
|
commonArgs.Add("/Oy-");
|
|
}
|
|
|
|
// Full Path of Source Code File in Diagnostics
|
|
commonArgs.Add("/FC");
|
|
|
|
// Report Internal Compiler Errors
|
|
commonArgs.Add("/errorReport:prompt");
|
|
|
|
// Exception Handling Model
|
|
if (!compileEnvironment.CompileAsWinRT)
|
|
{
|
|
if (compileEnvironment.EnableExceptions)
|
|
commonArgs.Add("/EHsc");
|
|
else
|
|
commonArgs.Add("/D_HAS_EXCEPTIONS=0");
|
|
}
|
|
|
|
// Eliminate Duplicate Strings
|
|
if (compileEnvironment.StringPooling)
|
|
commonArgs.Add("/GF");
|
|
else
|
|
commonArgs.Add("/GF-");
|
|
|
|
// Use Run-Time Library
|
|
if (compileEnvironment.UseDebugCRT)
|
|
commonArgs.Add("/MDd");
|
|
else
|
|
commonArgs.Add("/MD");
|
|
|
|
// Specify floating-point behavior
|
|
commonArgs.Add("/fp:fast");
|
|
commonArgs.Add("/fp:except-");
|
|
|
|
// Buffer Security Check
|
|
if (compileEnvironment.BufferSecurityCheck)
|
|
commonArgs.Add("/GS");
|
|
else
|
|
commonArgs.Add("/GS-");
|
|
|
|
// Enable Run-Time Type Information
|
|
if (compileEnvironment.RuntimeTypeInfo)
|
|
commonArgs.Add("/GR");
|
|
else
|
|
commonArgs.Add("/GR-");
|
|
|
|
// Treats all compiler warnings as errors
|
|
if (compileEnvironment.TreatWarningsAsErrors)
|
|
commonArgs.Add("/WX");
|
|
else
|
|
commonArgs.Add("/WX-");
|
|
|
|
// Show warnings
|
|
commonArgs.Add("/W3");
|
|
|
|
// Silence macro redefinition warning
|
|
commonArgs.Add("/wd\"4005\"");
|
|
|
|
// wchar_t is Native Type
|
|
commonArgs.Add("/Zc:wchar_t");
|
|
|
|
// Common Language Runtime Compilation
|
|
if (compileEnvironment.CompileAsWinRT)
|
|
commonArgs.Add("/clr");
|
|
|
|
// Windows Runtime Compilation
|
|
if (compileEnvironment.WinRTComponentExtensions)
|
|
{
|
|
commonArgs.Add("/ZW");
|
|
//commonArgs.Add("/ZW:nostdlib");
|
|
|
|
var dir = GetCppCXMetadataDirectory();
|
|
if (dir != null)
|
|
{
|
|
commonArgs.Add(string.Format("/AI\"{0}\"", dir));
|
|
commonArgs.Add(string.Format("/FU\"{0}\\platform.winmd\"", dir));
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add preprocessor definitions
|
|
foreach (var definition in compileEnvironment.PreprocessorDefinitions)
|
|
{
|
|
commonArgs.Add(string.Format("/D \"{0}\"", definition));
|
|
}
|
|
|
|
// Add include paths
|
|
foreach (var includePath in compileEnvironment.IncludePaths)
|
|
{
|
|
AddIncludePath(commonArgs, includePath);
|
|
}
|
|
|
|
var args = new List<string>();
|
|
|
|
// Create precompiled header
|
|
string pchFile = null, pchSource = null;
|
|
if (compileEnvironment.PrecompiledHeaderUsage == PrecompiledHeaderFileUsage.UseManual)
|
|
{
|
|
pchFile = compileEnvironment.PrecompiledHeaderFile;
|
|
pchSource = compileEnvironment.PrecompiledHeaderSource;
|
|
}
|
|
else if (compileEnvironment.PrecompiledHeaderUsage == PrecompiledHeaderFileUsage.CreateManual)
|
|
{
|
|
// Use intermediate cpp file that includes the PCH path but also contains compiler info to properly recompile when it's modified
|
|
pchSource = compileEnvironment.PrecompiledHeaderSource;
|
|
var pchFilName = Path.GetFileName(pchSource);
|
|
var pchSourceFile = Path.Combine(options.IntermediateFolder, Path.ChangeExtension(pchFilName, "cpp"));
|
|
var contents = Bindings.BindingsGenerator.GetStringBuilder();
|
|
contents.AppendLine("// This code was auto-generated. Do not modify it.");
|
|
// TODO: write compiler version to properly rebuild pch on Visual Studio updates
|
|
contents.Append("// Compiler: ").AppendLine(_compilerPath);
|
|
contents.Append("#include \"").Append(pchSource).AppendLine("\"");
|
|
Utilities.WriteFileIfChanged(pchSourceFile, contents.ToString());
|
|
Bindings.BindingsGenerator.PutStringBuilder(contents);
|
|
|
|
// Compile intermediate cpp file into actual PCH (and obj+pdb files)
|
|
pchFile = Path.Combine(options.IntermediateFolder, Path.ChangeExtension(pchFilName, "pch"));
|
|
if (pchFile.EndsWith(".pch.pch"))
|
|
pchFile = pchFile.Substring(0, pchFile.Length - 4);
|
|
var pchPdbFile = Path.Combine(options.IntermediateFolder, Path.ChangeExtension(pchFilName, "pdb"));
|
|
var pchObjFile = Path.Combine(options.IntermediateFolder, Path.ChangeExtension(pchFilName, "obj"));
|
|
var task = graph.Add<Task>();
|
|
task.PrerequisiteFiles.Add(pchSourceFile);
|
|
task.PrerequisiteFiles.Add(pchSource);
|
|
task.PrerequisiteFiles.AddRange(IncludesCache.FindAllIncludedFiles(pchSource));
|
|
task.ProducedFiles.Add(pchFile);
|
|
task.ProducedFiles.Add(pchObjFile);
|
|
args.AddRange(commonArgs);
|
|
args.Add(string.Format("/Yc\"{0}\"", pchSource));
|
|
args.Add(string.Format("/Fp\"{0}\"", pchFile));
|
|
args.Add(string.Format("/Fd\"{0}\"", pchPdbFile));
|
|
args.Add(string.Format("/Fo\"{0}\"", pchObjFile));
|
|
args.Add("/FS");
|
|
args.Add(string.Format("\"{0}\"", pchSourceFile));
|
|
task.WorkingDirectory = options.WorkingDirectory;
|
|
task.CommandPath = _compilerPath;
|
|
task.CommandArguments = string.Join(" ", args);
|
|
task.Cost = int.MaxValue; // Run it before any other tasks
|
|
|
|
// Setup outputs
|
|
output.PrecompiledHeaderFile = pchFile;
|
|
output.ObjectFiles.Add(pchObjFile);
|
|
}
|
|
if (pchFile != null)
|
|
{
|
|
// Include PCH file
|
|
commonArgs.Add(string.Format("/FI\"{0}\"", pchSource));
|
|
commonArgs.Add(string.Format("/Yu\"{0}\"", pchSource));
|
|
commonArgs.Add(string.Format("/Fp\"{0}\"", pchFile));
|
|
}
|
|
|
|
// Compile all C++ files
|
|
foreach (var sourceFile in sourceFiles)
|
|
{
|
|
var sourceFilename = Path.GetFileNameWithoutExtension(sourceFile);
|
|
var task = graph.Add<CompileCppTask>();
|
|
|
|
// Use shared arguments
|
|
args.Clear();
|
|
args.AddRange(commonArgs);
|
|
|
|
if (compileEnvironment.DebugInformation)
|
|
{
|
|
// Program Database File Name
|
|
string pdbFile = null;
|
|
if (pchFile != null)
|
|
{
|
|
// When using PCH we need to share the same PDB file that was used when building PCH
|
|
pdbFile = pchFile + ".pdb";
|
|
|
|
// Turn on sync for file access to prevent issues when compiling on multiple threads at once
|
|
if (useSeparatePdb)
|
|
args.Add("/FS");
|
|
}
|
|
else if (useSeparatePdb)
|
|
{
|
|
pdbFile = Path.Combine(outputPath, sourceFilename + ".pdb");
|
|
}
|
|
if (pdbFile != null)
|
|
{
|
|
args.Add(string.Format("/Fd\"{0}\"", pdbFile));
|
|
output.DebugDataFiles.Add(pdbFile);
|
|
}
|
|
}
|
|
|
|
if (compileEnvironment.GenerateDocumentation)
|
|
{
|
|
// Process Documentation Comments
|
|
var docFile = Path.Combine(outputPath, sourceFilename + ".xdc");
|
|
args.Add(string.Format("/doc\"{0}\"", docFile));
|
|
output.DocumentationFiles.Add(docFile);
|
|
}
|
|
|
|
// Object File Name
|
|
var objFile = Path.Combine(outputPath, sourceFilename + ".obj");
|
|
args.Add(string.Format("/Fo\"{0}\"", objFile));
|
|
output.ObjectFiles.Add(objFile);
|
|
task.ProducedFiles.Add(objFile);
|
|
|
|
// Source File Name
|
|
args.Add("\"" + sourceFile + "\"");
|
|
|
|
// Request included files to exist
|
|
var includes = IncludesCache.FindAllIncludedFiles(sourceFile);
|
|
task.PrerequisiteFiles.AddRange(includes);
|
|
if (pchFile != null)
|
|
{
|
|
task.PrerequisiteFiles.Add(pchFile);
|
|
}
|
|
|
|
// Compile
|
|
task.WorkingDirectory = options.WorkingDirectory;
|
|
task.CommandPath = _compilerPath;
|
|
task.CommandArguments = string.Join(" ", args);
|
|
task.PrerequisiteFiles.Add(sourceFile);
|
|
task.Cost = task.PrerequisiteFiles.Count; // TODO: include source file size estimation to improve tasks sorting
|
|
}
|
|
|
|
return output;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public override void LinkFiles(TaskGraph graph, BuildOptions options, string outputFilePath)
|
|
{
|
|
var linkEnvironment = options.LinkEnv;
|
|
var task = graph.Add<LinkTask>();
|
|
|
|
// Setup arguments
|
|
var args = new List<string>();
|
|
args.AddRange(options.LinkEnv.CustomArgs);
|
|
SetupLinkFilesArgs(graph, options, args);
|
|
{
|
|
// Suppress startup banner
|
|
args.Add("/NOLOGO");
|
|
|
|
// Report internal compiler errors
|
|
args.Add("/ERRORREPORT:PROMPT");
|
|
|
|
// Output File Name
|
|
args.Add(string.Format("/OUT:\"{0}\"", outputFilePath));
|
|
|
|
// Specify target platform
|
|
switch (Architecture)
|
|
{
|
|
case TargetArchitecture.x86:
|
|
args.Add("/MACHINE:x86");
|
|
break;
|
|
case TargetArchitecture.x64:
|
|
args.Add("/MACHINE:x64");
|
|
break;
|
|
case TargetArchitecture.ARM:
|
|
case TargetArchitecture.ARM64:
|
|
args.Add("/MACHINE:ARM");
|
|
break;
|
|
default: throw new InvalidArchitectureException(Architecture);
|
|
}
|
|
|
|
// Specify subsystem
|
|
if (linkEnvironment.LinkAsConsoleProgram)
|
|
{
|
|
args.Add("/SUBSYSTEM:CONSOLE");
|
|
}
|
|
else
|
|
{
|
|
args.Add("/SUBSYSTEM:WINDOWS");
|
|
}
|
|
|
|
// Generate Windows Metadata
|
|
if (linkEnvironment.GenerateWindowsMetadata)
|
|
{
|
|
args.Add("/WINMD");
|
|
args.Add(string.Format("/WINMDFILE:\"{0}\"", Path.ChangeExtension(outputFilePath, "winmd")));
|
|
args.Add("/APPCONTAINER");
|
|
if (linkEnvironment.Output == LinkerOutput.SharedLibrary)
|
|
args.Add("/DYNAMICBASE");
|
|
}
|
|
|
|
if (linkEnvironment.LinkTimeCodeGeneration)
|
|
{
|
|
// Link-time code generation
|
|
args.Add("/LTCG");
|
|
}
|
|
|
|
if (linkEnvironment.Output == LinkerOutput.ImportLibrary)
|
|
{
|
|
// Create an import library
|
|
args.Add("/DEF");
|
|
|
|
// Ignore libraries
|
|
args.Add("/NODEFAULTLIB");
|
|
|
|
// Specify the name
|
|
args.Add(string.Format("/NAME:\"{0}\"", Path.GetFileNameWithoutExtension(outputFilePath)));
|
|
|
|
// Ignore warnings about files with no public symbols
|
|
args.Add("/IGNORE:4221");
|
|
}
|
|
else
|
|
{
|
|
// Don't create Side-by-Side Assembly Manifest
|
|
args.Add("/MANIFEST:NO");
|
|
|
|
// Fixed Base Address
|
|
args.Add("/FIXED:NO");
|
|
|
|
if (Architecture == TargetArchitecture.x86)
|
|
{
|
|
// Handle Large Addresses
|
|
args.Add("/LARGEADDRESSAWARE");
|
|
}
|
|
|
|
// Compatible with Data Execution Prevention
|
|
args.Add("/NXCOMPAT");
|
|
|
|
// Allow delay-loaded DLLs to be explicitly unloaded
|
|
args.Add("/DELAY:UNLOAD");
|
|
|
|
if (linkEnvironment.Output == LinkerOutput.SharedLibrary)
|
|
{
|
|
// Build a DLL
|
|
args.Add("/DLL");
|
|
}
|
|
|
|
// Redirect imports LIB file auto-generated for EXE/DLL
|
|
var libFile = Path.ChangeExtension(outputFilePath, Platform.StaticLibraryFileExtension);
|
|
args.Add("/IMPLIB:\"" + libFile + "\"");
|
|
task.ProducedFiles.Add(libFile);
|
|
|
|
// Don't embed the full PDB path
|
|
args.Add("/PDBALTPATH:%_PDB%");
|
|
|
|
// Optimize
|
|
if (linkEnvironment.Optimization && !linkEnvironment.UseIncrementalLinking)
|
|
{
|
|
// Generate an EXE checksum
|
|
args.Add("/RELEASE");
|
|
|
|
// Eliminate unreferenced symbols
|
|
args.Add("/OPT:REF");
|
|
|
|
// Remove redundant COMDATs
|
|
args.Add("/OPT:ICF");
|
|
}
|
|
else
|
|
{
|
|
// Keep symbols that are unreferenced
|
|
args.Add("/OPT:NOREF");
|
|
|
|
// Disable identical COMDAT folding
|
|
args.Add("/OPT:NOICF");
|
|
}
|
|
|
|
// Link Incrementally
|
|
if (linkEnvironment.UseIncrementalLinking)
|
|
{
|
|
args.Add("/INCREMENTAL");
|
|
}
|
|
else
|
|
{
|
|
args.Add("/INCREMENTAL:NO");
|
|
}
|
|
|
|
if (linkEnvironment.DebugInformation)
|
|
{
|
|
// Generate debug information
|
|
if (Toolset != WindowsPlatformToolset.v140 && linkEnvironment.UseFastPDBLinking)
|
|
{
|
|
args.Add("/DEBUG:FASTLINK");
|
|
}
|
|
else if (linkEnvironment.UseFullDebugInformation)
|
|
{
|
|
args.Add("/DEBUG:FULL");
|
|
}
|
|
else
|
|
{
|
|
args.Add("/DEBUG"); // Same as /DEBUG:FULL
|
|
}
|
|
|
|
// Use Program Database
|
|
var pdbFile = Path.ChangeExtension(outputFilePath, Platform.ProgramDatabaseFileExtension);
|
|
args.Add(string.Format("/PDB:\"{0}\"", pdbFile));
|
|
task.ProducedFiles.Add(pdbFile);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Delay-load DLLs
|
|
if (linkEnvironment.Output == LinkerOutput.Executable || linkEnvironment.Output == LinkerOutput.SharedLibrary)
|
|
{
|
|
foreach (var dll in options.DelayLoadLibraries)
|
|
{
|
|
args.Add(string.Format("/DELAYLOAD:\"{0}\"", dll));
|
|
}
|
|
}
|
|
|
|
// Additional lib paths
|
|
foreach (var libpath in linkEnvironment.LibraryPaths)
|
|
{
|
|
args.Add(string.Format("/LIBPATH:\"{0}\"", libpath));
|
|
}
|
|
|
|
// Input libraries
|
|
task.PrerequisiteFiles.AddRange(linkEnvironment.InputLibraries);
|
|
foreach (var library in linkEnvironment.InputLibraries)
|
|
{
|
|
args.Add(string.Format("\"{0}\"", library));
|
|
}
|
|
|
|
// Input files
|
|
task.PrerequisiteFiles.AddRange(linkEnvironment.InputFiles);
|
|
foreach (var file in linkEnvironment.InputFiles)
|
|
{
|
|
if (file.EndsWith(".pch", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
// PCH file
|
|
args.Add(string.Format("/Yu:\"{0}\"", file));
|
|
continue;
|
|
}
|
|
|
|
args.Add(string.Format("\"{0}\"", file));
|
|
}
|
|
|
|
// Use a response file (it can contain any commands that you would specify on the command line)
|
|
bool useResponseFile = true;
|
|
string responseFile = null;
|
|
if (useResponseFile)
|
|
{
|
|
responseFile = Path.Combine(options.IntermediateFolder, Path.GetFileName(outputFilePath) + ".response");
|
|
task.PrerequisiteFiles.Add(responseFile);
|
|
Utilities.WriteFileIfChanged(responseFile, string.Join(Environment.NewLine, args));
|
|
}
|
|
|
|
// Link
|
|
task.WorkingDirectory = options.WorkingDirectory;
|
|
task.CommandPath = linkEnvironment.Output == LinkerOutput.ImportLibrary ? _libToolPath : _linkerPath;
|
|
task.CommandArguments = useResponseFile ? string.Format("@\"{0}\"", responseFile) : string.Join(" ", args);
|
|
if (linkEnvironment.Output == LinkerOutput.ImportLibrary)
|
|
task.InfoMessage = "Building import library " + outputFilePath;
|
|
else
|
|
task.InfoMessage = "Linking " + outputFilePath;
|
|
task.Cost = task.PrerequisiteFiles.Count;
|
|
task.ProducedFiles.Add(outputFilePath);
|
|
|
|
// Check if need to generate documentation
|
|
if (linkEnvironment.GenerateDocumentation)
|
|
{
|
|
args.Clear();
|
|
var docTask = graph.Add<Task>();
|
|
|
|
// Use old input format
|
|
args.Add("/old");
|
|
args.Add(string.Format("\"{0}\"", Path.GetFileNameWithoutExtension(outputFilePath)));
|
|
|
|
// Suppress copyright message
|
|
args.Add("/nologo");
|
|
|
|
// Output file
|
|
var outputDocFile = Path.ChangeExtension(outputFilePath, "xml");
|
|
docTask.ProducedFiles.Add(outputDocFile);
|
|
args.Add(string.Format("/Fo\"{0}\"", outputDocFile));
|
|
|
|
// Input files
|
|
docTask.PrerequisiteFiles.AddRange(linkEnvironment.DocumentationFiles);
|
|
foreach (var file in linkEnvironment.DocumentationFiles)
|
|
{
|
|
args.Add(string.Format("/Fs\"{0}\"", file));
|
|
}
|
|
|
|
// Generate docs
|
|
docTask.WorkingDirectory = options.WorkingDirectory;
|
|
docTask.CommandPath = _xdcmakePath;
|
|
docTask.CommandArguments = string.Join(" ", args);
|
|
docTask.Cost = linkEnvironment.DocumentationFiles.Count;
|
|
}
|
|
|
|
// Check if need to generate metadata file
|
|
if (linkEnvironment.GenerateWindowsMetadata)
|
|
{
|
|
var configFile = Path.Combine(options.IntermediateFolder, Path.GetFileNameWithoutExtension(outputFilePath) + ".priconfig.xml");
|
|
var manifestFile = Path.Combine(options.IntermediateFolder, Path.GetFileNameWithoutExtension(outputFilePath) + ".AppxManifest.xml");
|
|
var priFile = Path.ChangeExtension(outputFilePath, "pri");
|
|
|
|
// Generate pri config file
|
|
var priConfigTask = graph.Add<Task>();
|
|
priConfigTask.WorkingDirectory = options.WorkingDirectory;
|
|
priConfigTask.CommandPath = _makepriPath;
|
|
priConfigTask.CommandArguments = string.Format("createconfig /cf \"{0}\" /dq en-US /o", configFile);
|
|
priConfigTask.Cost = 1;
|
|
priConfigTask.ProducedFiles.Add(configFile);
|
|
|
|
// Create AppxManifest file
|
|
{
|
|
using (var stringWriter = new StringWriterWithEncoding(Encoding.UTF8))
|
|
using (var xmlTextWriter = XmlWriter.Create(stringWriter, new XmlWriterSettings { Encoding = Encoding.UTF8, Indent = true, }))
|
|
{
|
|
xmlTextWriter.WriteStartDocument();
|
|
|
|
// Package
|
|
{
|
|
xmlTextWriter.WriteStartElement("Package", "http://schemas.microsoft.com/appx/2010/manifest");
|
|
|
|
// Identity
|
|
{
|
|
xmlTextWriter.WriteStartElement("Identity");
|
|
|
|
xmlTextWriter.WriteAttributeString("Name", "FlaxGame");
|
|
xmlTextWriter.WriteAttributeString("Publisher", "CN=Flax, O=Flax, C=Poland");
|
|
xmlTextWriter.WriteAttributeString("Version", "1.0.0.0"); // TODO: get Flax version number
|
|
|
|
switch (Architecture)
|
|
{
|
|
case TargetArchitecture.AnyCPU:
|
|
xmlTextWriter.WriteAttributeString("ProcessorArchitecture", "neutral");
|
|
break;
|
|
case TargetArchitecture.x86:
|
|
xmlTextWriter.WriteAttributeString("ProcessorArchitecture", "x86");
|
|
break;
|
|
case TargetArchitecture.x64:
|
|
xmlTextWriter.WriteAttributeString("ProcessorArchitecture", "x64");
|
|
break;
|
|
case TargetArchitecture.ARM:
|
|
case TargetArchitecture.ARM64:
|
|
xmlTextWriter.WriteAttributeString("ProcessorArchitecture", "arm");
|
|
break;
|
|
default: throw new InvalidArchitectureException(Architecture);
|
|
}
|
|
|
|
xmlTextWriter.WriteEndElement();
|
|
}
|
|
|
|
// Properties
|
|
{
|
|
xmlTextWriter.WriteStartElement("Properties");
|
|
|
|
// TODO: better logo handling
|
|
var logoSrcPath = Path.Combine(Globals.EngineRoot, "Source", "Logo.png");
|
|
var logoDstPath = Path.Combine(options.IntermediateFolder, "Logo.png");
|
|
if (!File.Exists(logoDstPath))
|
|
Utilities.FileCopy(logoSrcPath, logoDstPath);
|
|
|
|
xmlTextWriter.WriteElementString("DisplayName", "FlaxGame");
|
|
xmlTextWriter.WriteElementString("PublisherDisplayName", "Flax");
|
|
xmlTextWriter.WriteElementString("Logo", "Logo.png");
|
|
|
|
xmlTextWriter.WriteEndElement();
|
|
}
|
|
|
|
// Resources
|
|
{
|
|
xmlTextWriter.WriteStartElement("Resources");
|
|
|
|
xmlTextWriter.WriteStartElement("Resource");
|
|
xmlTextWriter.WriteAttributeString("Language", "en-us");
|
|
xmlTextWriter.WriteEndElement();
|
|
|
|
xmlTextWriter.WriteEndElement();
|
|
}
|
|
|
|
// Prerequisites
|
|
{
|
|
xmlTextWriter.WriteStartElement("Prerequisites");
|
|
|
|
xmlTextWriter.WriteElementString("OSMinVersion", "6.2");
|
|
xmlTextWriter.WriteElementString("OSMaxVersionTested", "6.2");
|
|
|
|
xmlTextWriter.WriteEndElement();
|
|
}
|
|
}
|
|
|
|
xmlTextWriter.WriteEndDocument();
|
|
xmlTextWriter.Flush();
|
|
|
|
// Save manifest to file
|
|
var contents = stringWriter.GetStringBuilder().ToString();
|
|
Utilities.WriteFileIfChanged(manifestFile, contents);
|
|
}
|
|
}
|
|
|
|
var dummyWorkspace = Path.Combine(options.IntermediateFolder, "Dummy");
|
|
if (!Directory.Exists(dummyWorkspace))
|
|
Directory.CreateDirectory(dummyWorkspace);
|
|
|
|
// Generate pri file
|
|
var priNewFile = graph.Add<Task>();
|
|
priNewFile.WorkingDirectory = options.WorkingDirectory;
|
|
priNewFile.CommandPath = _makepriPath;
|
|
priNewFile.CommandArguments = string.Format("new /cf \"{0}\" /pr \"{1}\" /of \"{2}\" /mn \"{3}\" /o", configFile, dummyWorkspace, priFile, manifestFile);
|
|
priNewFile.Cost = 1;
|
|
priNewFile.PrerequisiteFiles.Add(configFile);
|
|
priNewFile.ProducedFiles.Add(priFile);
|
|
}
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public override bool CompileCSharp(ref CSharpOptions options)
|
|
{
|
|
switch (options.Action)
|
|
{
|
|
case CSharpOptions.ActionTypes.MonoCompile:
|
|
{
|
|
var aotCompilerPath = Path.Combine(options.PlatformToolsPath, "mono-aot-cross.exe");
|
|
|
|
// Setup options
|
|
var monoAotMode = "full";
|
|
var monoDebugMode = options.EnableDebugSymbols ? "soft-debug" : "nodebug";
|
|
var aotCompilerArgs = $"--aot={monoAotMode},verbose,stats,print-skipped,{monoDebugMode} -O=all";
|
|
if (options.EnableDebugSymbols || options.EnableToolDebug)
|
|
aotCompilerArgs = "--debug " + aotCompilerArgs;
|
|
var envVars = new Dictionary<string, string>();
|
|
envVars["MONO_PATH"] = options.AssembliesPath + ";" + options.ClassLibraryPath;
|
|
if (options.EnableToolDebug)
|
|
{
|
|
envVars["MONO_LOG_LEVEL"] = "debug";
|
|
}
|
|
|
|
// Run cross-compiler compiler
|
|
int result = Utilities.Run(aotCompilerPath, $"{aotCompilerArgs} \"{options.InputFiles[0]}\"", null, options.PlatformToolsPath, Utilities.RunOptions.AppMustExist | Utilities.RunOptions.ConsoleLogOutput, envVars);
|
|
return result != 0;
|
|
}
|
|
}
|
|
return base.CompileCSharp(ref options);
|
|
}
|
|
}
|
|
}
|