dotnet-installer/src/Microsoft.DotNet.Tools.Compiler.Native/IntermediateCompilation/Windows/WindowsLinkStep.cs

153 lines
4.5 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using Microsoft.Dnx.Runtime.Common.CommandLine;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Tools.Common;
namespace Microsoft.DotNet.Tools.Compiler.Native
{
public class WindowsLinkStep : IPlatformNativeStep
{
private readonly string LinkerName = "link.exe";
private readonly string LinkerOutputExtension = ".exe";
2015-11-17 17:02:16 -08:00
private readonly string VSBin = "..\\..\\VC\\bin\\amd64";
private readonly string InputExtension = ".obj";
private static readonly Dictionary<BuildConfiguration, string> ConfigurationLinkerOptionsMap = new Dictionary<BuildConfiguration, string>
{
{ BuildConfiguration.debug, "/NOLOGO /ERRORREPORT:PROMPT /MANIFEST /MANIFESTUAC:\"level='asInvoker' uiAccess='false'\" /manifest:embed /Debug /SUBSYSTEM:CONSOLE /TLBID:1 /DYNAMICBASE /NXCOMPAT" },
{ BuildConfiguration.release, "/NOLOGO /ERRORREPORT:PROMPT /INCREMENTAL:NO /OPT:REF /OPT:ICF /LTCG:incremental /MANIFEST /MANIFESTUAC:\"level='asInvoker' uiAccess='false'\" /manifest:embed /Debug /SUBSYSTEM:CONSOLE /TLBID:1 /DYNAMICBASE /NXCOMPAT" }
};
private static readonly Dictionary<NativeIntermediateMode, string[]> ModeLibMap = new Dictionary<NativeIntermediateMode, string[]>
{
{ NativeIntermediateMode.cpp, new string[] { "PortableRuntime.lib", "bootstrappercpp.lib" } },
{ NativeIntermediateMode.ryujit, new string[] { "Runtime.lib", "bootstrapper.lib" } }
};
private static readonly string[] ConstantLinkLibs = new string[]
{
"kernel32.lib",
"user32.lib",
"gdi32.lib",
"winspool.lib",
"comdlg32.lib",
"advapi32.lib",
"shell32.lib",
"ole32.lib",
"oleaut32.lib",
"uuid.lib",
"odbc32.lib",
"odbccp32.lib"
};
private string ArgStr { get; set; }
2015-11-17 19:50:19 -08:00
private NativeCompileSettings config;
public WindowsLinkStep(NativeCompileSettings config)
{
2015-11-17 19:50:19 -08:00
this.config = config;
InitializeArgs(config);
}
2015-11-17 19:50:19 -08:00
public int Invoke()
{
var result = WindowsCommon.SetVCVars();
if (result != 0)
{
Reporter.Error.WriteLine("vcvarsall.bat invocation failed.");
return result;
}
2015-11-17 19:50:19 -08:00
result = InvokeLinker();
if (result != 0)
{
Reporter.Error.WriteLine("Linking of intermediate files failed.");
}
return result;
}
public bool CheckPreReqs()
{
var vcInstallDir = Environment.GetEnvironmentVariable("VS140COMNTOOLS");
return !string.IsNullOrEmpty(vcInstallDir);
}
private void InitializeArgs(NativeCompileSettings config)
{
var argsList = new List<string>();
// Configuration Based Linker Options
argsList.Add(ConfigurationLinkerOptionsMap[config.BuildType]);
//Output
var outFile = DetermineOutputFile(config);
argsList.Add($"/out:\"{outFile}\"");
// Constant Libs
argsList.Add(string.Join(" ", ConstantLinkLibs));
// SDK Libs
var SDKLibs = ModeLibMap[config.NativeMode];
foreach (var lib in SDKLibs)
{
2015-11-17 19:50:19 -08:00
argsList.Add(Path.Combine(config.IlcPath, lib));
}
// Link Libs
foreach(var path in config.LinkLibPaths){
argsList.Add($"\"{path}\"");
}
//arch
argsList.Add($"/MACHINE:{config.Architecture}");
//Input Obj file
var inputFile = DetermineInputFile(config);
argsList.Add($"\"{inputFile}\"");
this.ArgStr = string.Join(" ", argsList);
}
2015-11-17 19:50:19 -08:00
private int InvokeLinker()
{
var vcInstallDir = Environment.GetEnvironmentVariable("VS140COMNTOOLS");
var linkerPath = Path.Combine(vcInstallDir, VSBin, LinkerName);
var result = Command.Create(linkerPath, ArgStr)
.ForwardStdErr()
.ForwardStdOut()
.Execute();
return result.ExitCode;
}
public string DetermineOutputFile(NativeCompileSettings config)
{
var outputDirectory = config.OutputDirectory;
var filename = Path.GetFileNameWithoutExtension(config.InputManagedAssemblyPath);
var outFile = Path.Combine(outputDirectory, filename + LinkerOutputExtension);
return outFile;
}
private string DetermineInputFile(NativeCompileSettings config)
{
var intermediateDirectory = config.IntermediateDirectory;
var filename = Path.GetFileNameWithoutExtension(config.InputManagedAssemblyPath);
var infile = Path.Combine(intermediateDirectory, filename + InputExtension);
return infile;
}
}
}