Merge pull request #243 from livarcocc/native_fixes

Fixes for dotnet compile --native.
This commit is contained in:
Livar 2015-11-19 12:26:54 -08:00
commit b3b2ee737f
7 changed files with 234 additions and 206 deletions

View file

@ -12,10 +12,20 @@ pushd %1
set __OutputPath=%CD%\bin set __OutputPath=%CD%\bin
popd popd
rmdir /S /Q %AppDepsProjectDir%\packages
pushd %__AppDepsProjectDir% pushd %__AppDepsProjectDir%
dotnet restore --packages %AppDepsProjectDir%\packages dotnet restore --packages %AppDepsProjectDir%\packages
set __AppDepSDK=%AppDepsProjectDir%\packages\toolchain*\*\ set __AppDepSDK=%AppDepsProjectDir%\packages\toolchain*\
popd popd
mkdir %__OutputPath%\appdepsdk mkdir %__OutputPath%\appdepsdk
xcopy /S/E/H/Y %__AppDepSDK% %__OutputPath%\appdepsdk cd %__AppDepSDK%
FOR /D %%a IN (*) DO (
CD %%a
GOTO :Copy
)
:Copy
xcopy /S/E/H/Y * %__OutputPath%\appdepsdk

View file

@ -29,6 +29,10 @@ namespace Microsoft.DotNet.Tools.Compiler.Native
Console.WriteLine(e.Message); Console.WriteLine(e.Message);
} }
} }
else
{
Directory.CreateDirectory(path);
}
} }
} }
} }

View file

@ -69,7 +69,7 @@ namespace Microsoft.DotNet.Tools.Compiler.Native
// Add Includes // Add Includes
argsList.Add("/I"); argsList.Add("/I");
argsList.Add(Path.Combine(config.AppDepSDKPath, "CPPSdk\\Windows_NT")); argsList.Add(Path.Combine(config.AppDepSDKPath, "CPPSdk\\win7"));
argsList.Add("/I"); argsList.Add("/I");
argsList.Add(Path.Combine(config.AppDepSDKPath, "CPPSdk")); argsList.Add(Path.Combine(config.AppDepSDKPath, "CPPSdk"));

View file

@ -10,19 +10,19 @@ using Microsoft.DotNet.Tools.Common;
namespace Microsoft.DotNet.Tools.Compiler.Native namespace Microsoft.DotNet.Tools.Compiler.Native
{ {
public class WindowsLinkStep : IPlatformNativeStep public class WindowsLinkStep : IPlatformNativeStep
{ {
private readonly string LinkerName = "link.exe"; private readonly string LinkerName = "link.exe";
private readonly string LinkerOutputExtension = ".exe"; private readonly string LinkerOutputExtension = ".exe";
private readonly string VSBin = "..\\..\\VC\\bin\\amd64"; private readonly string VSBin = "..\\..\\VC\\bin\\amd64";
private readonly string InputExtension = ".obj"; private readonly string InputExtension = ".obj";
private static readonly Dictionary<BuildConfiguration, string> ConfigurationLinkerOptionsMap = new Dictionary<BuildConfiguration, string> 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.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" } { 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[]> private static readonly Dictionary<NativeIntermediateMode, string[]> ModeLibMap = new Dictionary<NativeIntermediateMode, string[]>
{ {
@ -45,98 +45,111 @@ namespace Microsoft.DotNet.Tools.Compiler.Native
"odbc32.lib", "odbc32.lib",
"odbccp32.lib" "odbccp32.lib"
}; };
private string ArgStr { get; set; } private static readonly Dictionary<BuildConfiguration, string[]> ConfigurationLinkLibMap = new Dictionary<BuildConfiguration, string[]>()
private NativeCompileSettings config; {
{ BuildConfiguration.debug , new string[] { "msvcrtd.lib" } },
public WindowsLinkStep(NativeCompileSettings config) { BuildConfiguration.release , new string[] { "msvcrt.lib" } }
{ };
this.config = config;
InitializeArgs(config); private string ArgStr { get; set; }
} private NativeCompileSettings config;
public int Invoke() public WindowsLinkStep(NativeCompileSettings config)
{ {
var result = WindowsCommon.SetVCVars(); this.config = config;
if (result != 0) InitializeArgs(config);
{ }
Reporter.Error.WriteLine("vcvarsall.bat invocation failed.");
return result; public int Invoke()
} {
var result = WindowsCommon.SetVCVars();
result = InvokeLinker(); if (result != 0)
if (result != 0) {
{ Reporter.Error.WriteLine("vcvarsall.bat invocation failed.");
return result;
}
result = InvokeLinker();
if (result != 0)
{
Reporter.Error.WriteLine("Linking of intermediate files failed."); Reporter.Error.WriteLine("Linking of intermediate files failed.");
} }
return result; return result;
} }
public bool CheckPreReqs() public bool CheckPreReqs()
{ {
var vcInstallDir = Environment.GetEnvironmentVariable("VS140COMNTOOLS"); var vcInstallDir = Environment.GetEnvironmentVariable("VS140COMNTOOLS");
return !string.IsNullOrEmpty(vcInstallDir); return !string.IsNullOrEmpty(vcInstallDir);
} }
private void InitializeArgs(NativeCompileSettings config) private void InitializeArgs(NativeCompileSettings config)
{ {
var argsList = new List<string>(); var argsList = new List<string>();
// Configuration Based Linker Options // Configuration Based Linker Options
argsList.Add(ConfigurationLinkerOptionsMap[config.BuildType]); argsList.Add(ConfigurationLinkerOptionsMap[config.BuildType]);
//Output //Output
var outFile = DetermineOutputFile(config); var outFile = DetermineOutputFile(config);
argsList.Add($"/out:\"{outFile}\""); argsList.Add($"/out:\"{outFile}\"");
// Constant Libs // Constant Libs
argsList.Add(string.Join(" ", ConstantLinkLibs)); argsList.Add(string.Join(" ", ConstantLinkLibs));
// SDK Libs // SDK Libs
var SDKLibs = ModeLibMap[config.NativeMode]; var SDKLibs = ModeLibMap[config.NativeMode];
foreach (var lib in SDKLibs) foreach (var lib in SDKLibs)
{ {
argsList.Add(Path.Combine(config.IlcPath, lib)); argsList.Add(Path.Combine(config.IlcPath, lib));
} }
// Link Libs // Configuration Based Libs
foreach(var path in config.LinkLibPaths){ var configLibs = ConfigurationLinkLibMap[config.BuildType];
argsList.Add($"\"{path}\""); foreach (var lib in configLibs)
} {
argsList.Add(lib);
//arch }
argsList.Add($"/MACHINE:{config.Architecture}");
// Link Libs
foreach(var path in config.LinkLibPaths){
argsList.Add($"\"{path}\"");
}
//arch
argsList.Add($"/MACHINE:{config.Architecture}");
//Input Obj file //Input Obj file
var inputFile = DetermineInputFile(config); var inputFile = DetermineInputFile(config);
argsList.Add($"\"{inputFile}\""); argsList.Add($"\"{inputFile}\"");
this.ArgStr = string.Join(" ", argsList); this.ArgStr = string.Join(" ", argsList);
} }
private int InvokeLinker() private int InvokeLinker()
{ {
var vcInstallDir = Environment.GetEnvironmentVariable("VS140COMNTOOLS"); var vcInstallDir = Environment.GetEnvironmentVariable("VS140COMNTOOLS");
var linkerPath = Path.Combine(vcInstallDir, VSBin, LinkerName); var linkerPath = Path.Combine(vcInstallDir, VSBin, LinkerName);
var result = Command.Create(linkerPath, ArgStr) var result = Command.Create(linkerPath, ArgStr)
.ForwardStdErr() .ForwardStdErr()
.ForwardStdOut() .ForwardStdOut()
.Execute(); .Execute();
return result.ExitCode; return result.ExitCode;
} }
public string DetermineOutputFile(NativeCompileSettings config) public string DetermineOutputFile(NativeCompileSettings config)
{ {
var outputDirectory = config.OutputDirectory; var outputDirectory = config.OutputDirectory;
var filename = Path.GetFileNameWithoutExtension(config.InputManagedAssemblyPath); var filename = Path.GetFileNameWithoutExtension(config.InputManagedAssemblyPath);
var outFile = Path.Combine(outputDirectory, filename + LinkerOutputExtension); var outFile = Path.Combine(outputDirectory, filename + LinkerOutputExtension);
return outFile; return outFile;
} }
private string DetermineInputFile(NativeCompileSettings config) private string DetermineInputFile(NativeCompileSettings config)
{ {
@ -148,6 +161,6 @@ namespace Microsoft.DotNet.Tools.Compiler.Native
return infile; return infile;
} }
} }
} }

View file

@ -1,6 +1,8 @@
using System; using System;
using System.Collections.Generic;
using System.CommandLine;
using System.IO; using System.IO;
using Microsoft.Dnx.Runtime.Common.CommandLine; using System.Linq;
using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Cli.Utils;
namespace Microsoft.DotNet.Tools.Compiler.Native namespace Microsoft.DotNet.Tools.Compiler.Native
@ -10,13 +12,76 @@ namespace Microsoft.DotNet.Tools.Compiler.Native
public static int Main(string[] args) public static int Main(string[] args)
{ {
DebugHelper.HandleDebugSwitch(ref args); DebugHelper.HandleDebugSwitch(ref args);
var app = SetupApp(); return ExecuteApp(args);
return ExecuteApp(app, args);
} }
private static int ExecuteApp(CommandLineApplication app, string[] args) private static ArgValues GetArgs(string[] args)
{
string inputAssembly = null;
string outputDirectory = null;
string temporaryOutputDirectory = null;
string configuration = null;
string mode = null;
string ilcArgs = null;
string ilcPath = null;
string appDepSdk = null;
string logPath = null;
IReadOnlyList<string> references = Array.Empty<string>();
IReadOnlyList<string> linklib = Array.Empty<string>();
try
{
ArgumentSyntax.Parse(args, syntax =>
{
syntax.DefineOption("output", ref outputDirectory, "Output Directory for native executable.");
syntax.DefineOption("temp-output", ref temporaryOutputDirectory, "Directory for intermediate files.");
syntax.DefineOption("configuration", ref configuration, "debug/release build configuration. Defaults to debug.");
syntax.DefineOption("mode", ref mode, "Code Generation mode. Defaults to ryujit.");
syntax.DefineOptionList("reference", ref references, "Use to specify Managed DLL references of the app.");
// Custom Extensibility Points to support CoreRT workflow TODO better descriptions
syntax.DefineOption("ilcargs", ref ilcArgs, "Use to specify custom arguments for the IL Compiler.");
syntax.DefineOption("ilcpath", ref ilcPath, "Use to plug in a custom built ilc.exe");
syntax.DefineOptionList("linklib", ref linklib, "Use to link in additional static libs");
// TEMPORARY Hack until CoreRT compatible Framework Libs are available
syntax.DefineOption("appdepsdk", ref appDepSdk, "Use to plug in custom appdepsdk path");
// Optional Log Path
syntax.DefineOption("logpath", ref logPath, "Use to dump Native Compilation Logs to a file.");
syntax.DefineParameter("INPUT_ASSEMBLY", ref inputAssembly, "The managed input assembly to compile to native.");
});
}
catch (ArgumentSyntaxException)
{
//return ExitFailed;
}
Console.WriteLine($"Input Assembly: {inputAssembly}");
return new ArgValues()
{
InputManagedAssemblyPath = inputAssembly,
OutputDirectory = outputDirectory,
IntermediateDirectory = temporaryOutputDirectory,
Architecture = "x64",
BuildConfiguration = configuration,
NativeMode = mode,
ReferencePaths = references.ToList(),
IlcArgs = ilcArgs,
IlcPath = ilcPath,
LinkLibPaths = linklib.ToList(),
AppDepSDKPath = appDepSdk,
LogPath = logPath
};
}
private static int ExecuteApp(string[] args)
{ {
// Support Response File // Support Response File
foreach(var arg in args) foreach(var arg in args)
@ -34,7 +99,17 @@ namespace Microsoft.DotNet.Tools.Compiler.Native
try try
{ {
return app.Execute(args); var cmdLineArgs = GetArgs(args);
var config = ParseAndValidateArgs(cmdLineArgs);
DirectoryExtensions.CleanOrCreateDirectory(config.OutputDirectory);
DirectoryExtensions.CleanOrCreateDirectory(config.IntermediateDirectory);
var nativeCompiler = NativeCompiler.Create(config);
var result = nativeCompiler.CompileToNative(config);
return result ? 0 : 1;
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -66,72 +141,9 @@ namespace Microsoft.DotNet.Tools.Compiler.Native
return null; return null;
} }
string[] nArgs = content.Split('\n'); string[] nArgs = content.Split(new [] {"\r\n", "\n"}, StringSplitOptions.RemoveEmptyEntries);
return nArgs; return nArgs;
} }
private static CommandLineApplication SetupApp()
{
var app = new CommandLineApplication
{
Name = "dotnet compile native",
FullName = "IL to Native compiler",
Description = "IL to Native compiler Compiler for the .NET Platform"
};
app.HelpOption("-h|--help");
var managedInputArg = app.Argument("<INPUT_ASSEMBLY>", "The managed input assembly to compile to native.");
var outputArg = app.Option("-o|--out <OUTPUT_DIR>", "Output Directory for native executable.", CommandOptionType.SingleValue);
var intermediateArg = app.Option("-t|--temp-output <OUTPUT_DIR>", "Directory for intermediate files.", CommandOptionType.SingleValue);
var buildConfigArg = app.Option("-c|--configuration <TYPE>", "debug/release build configuration. Defaults to debug.", CommandOptionType.SingleValue);
var modeArg = app.Option("-m|--mode <MODE>", "Code Generation mode. Defaults to ryujit. ", CommandOptionType.SingleValue);
var referencesArg = app.Option("-r|--reference <REF_PATH>", "Use to specify Managed DLL references of the app.", CommandOptionType.MultipleValue);
// Custom Extensibility Points to support CoreRT workflow TODO better descriptions
var ilcArgs = app.Option("--ilcargs <CODEGEN>", "Use to specify custom arguments for the IL Compiler.", CommandOptionType.SingleValue);
var ilcPathArg = app.Option("--ilcpath <ILC_PATH>", "Use to plug in a custom built ilc.exe", CommandOptionType.SingleValue);
var linklibArg = app.Option("--linklib <LINKLIB>", "Use to link in additional static libs", CommandOptionType.MultipleValue);
// TEMPORARY Hack until CoreRT compatible Framework Libs are available
var appdepSdkPathArg = app.Option("--appdepsdk <SDK>", "Use to plug in custom appdepsdk path", CommandOptionType.SingleValue);
// Optional Log Path
var logpathArg = app.Option("--logpath <LOG_PATH>", "Use to dump Native Compilation Logs to a file.", CommandOptionType.SingleValue);
app.OnExecute(() =>
{
var cmdLineArgs = new ArgValues()
{
InputManagedAssemblyPath = managedInputArg.Value,
OutputDirectory = outputArg.Value(),
IntermediateDirectory = intermediateArg.Value(),
Architecture = "x64",
BuildConfiguration = buildConfigArg.Value(),
NativeMode = modeArg.Value(),
ReferencePaths = referencesArg.Values,
IlcArgs = ilcArgs.Value(),
IlcPath = ilcPathArg.Value(),
LinkLibPaths = linklibArg.Values,
AppDepSDKPath = appdepSdkPathArg.Value(),
LogPath = logpathArg.Value()
};
var config = ParseAndValidateArgs(cmdLineArgs);
DirectoryExtensions.CleanOrCreateDirectory(config.OutputDirectory);
DirectoryExtensions.CleanOrCreateDirectory(config.IntermediateDirectory);
var nativeCompiler = NativeCompiler.Create(config);
var result = nativeCompiler.CompileToNative(config);
return result ? 0 : 1;
});
return app;
}
private static NativeCompileSettings ParseAndValidateArgs(ArgValues args) private static NativeCompileSettings ParseAndValidateArgs(ArgValues args)
{ {

View file

@ -23,9 +23,10 @@
"type": "build", "type": "build",
"version": "1.0.0-*" "version": "1.0.0-*"
}, },
"Microsoft.DotNet.ILCompiler": "1.0.1-*", "Microsoft.DotNet.ILCompiler": "1.0.1-*",
"Microsoft.DotNet.ObjectWriter": "1.0.2-*", "Microsoft.DotNet.ObjectWriter": "1.0.2-*",
"Microsoft.DotNet.RyuJit": "1.0.0-*" "Microsoft.DotNet.RyuJit": "1.0.0-*",
"Microsoft.DotNet.Compiler.Common": "1.0.0-*"
}, },
"frameworks": { "frameworks": {
"dnxcore50": { } "dnxcore50": { }

View file

@ -92,25 +92,39 @@ namespace Microsoft.DotNet.Tools.Compiler
} }
} }
private static bool CompileNative(ProjectContext context, string configuration, string outputOptionValue, bool buildProjectReferences, string intermediateOutputValue, string archValue, string ilcArgsValue, bool isCppMode) private static bool CompileNative(
ProjectContext context,
string configuration,
string outputOptionValue,
bool buildProjectReferences,
string intermediateOutputValue,
string archValue,
string ilcArgsValue,
bool isCppMode)
{ {
var outputPath = Path.Combine(GetOutputPath(context, configuration, outputOptionValue), "native"); var outputPath = GetOutputPath(context, configuration, outputOptionValue);
var intermediateOutputPath = GetIntermediateOutputPath(context, configuration, intermediateOutputValue, outputOptionValue); var nativeOutputPath = Path.Combine(GetOutputPath(context, configuration, outputOptionValue), "native");
var intermediateOutputPath =
GetIntermediateOutputPath(context, configuration, intermediateOutputValue, outputOptionValue);
Directory.CreateDirectory(outputPath); Directory.CreateDirectory(nativeOutputPath);
Directory.CreateDirectory(intermediateOutputPath); Directory.CreateDirectory(intermediateOutputPath);
var compilationOptions = context.ProjectFile.GetCompilerOptions(context.TargetFramework, configuration); var compilationOptions = context.ProjectFile.GetCompilerOptions(context.TargetFramework, configuration);
var managedOutput = GetProjectOutput(context.ProjectFile, context.TargetFramework, configuration, outputPath); var managedOutput =
GetProjectOutput(context.ProjectFile, context.TargetFramework, configuration, outputPath);
var nativeArgs = new List<string>(); var nativeArgs = new List<string>();
// Input Assembly // Input Assembly
nativeArgs.Add($"\"{managedOutput}\""); nativeArgs.Add($"{managedOutput}");
// ILC Args // ILC Args
nativeArgs.Add("--ilcargs"); if (!string.IsNullOrWhiteSpace(ilcArgsValue))
nativeArgs.Add($"\"{ilcArgsValue}\""); {
nativeArgs.Add("--ilcargs");
nativeArgs.Add($"{ilcArgsValue}");
}
// CodeGen Mode // CodeGen Mode
if(isCppMode) if(isCppMode)
@ -135,37 +149,11 @@ namespace Microsoft.DotNet.Tools.Compiler
// Intermediate Path // Intermediate Path
nativeArgs.Add("--temp-output"); nativeArgs.Add("--temp-output");
nativeArgs.Add($"\"{intermediateOutputPath}\""); nativeArgs.Add($"{intermediateOutputPath}");
// Output Path // Output Path
nativeArgs.Add("--output"); nativeArgs.Add("--output");
nativeArgs.Add($"\"{outputPath}\""); nativeArgs.Add($"{nativeOutputPath}");
// Dependencies
var exporter = context.CreateExporter(configuration);
var dependencies = exporter.GetDependencies().ToList();
foreach (var dependency in dependencies)
{
var projectDependency = dependency.Library as ProjectDescription;
if (projectDependency != null)
{
if (projectDependency.Project.Files.SourceFiles.Any())
{
var projectOutputPath = GetProjectOutput(projectDependency.Project, projectDependency.Framework, configuration, outputPath);
nativeArgs.Add("-r");
nativeArgs.Add($"\"{projectOutputPath}\"");
}
}
else
{
foreach(var dep in dependency.RuntimeAssemblies)
{
nativeArgs.Add("-r");
nativeArgs.Add($"\"{dep.ResolvedPath}\"");
}
}
}
// Write Response File // Write Response File
var rsp = Path.Combine(intermediateOutputPath, $"dotnet-compile-native.{context.ProjectFile.Name}.rsp"); var rsp = Path.Combine(intermediateOutputPath, $"dotnet-compile-native.{context.ProjectFile.Name}.rsp");
@ -175,7 +163,7 @@ namespace Microsoft.DotNet.Tools.Compiler
// Need CoreRT Framework published to nuget // Need CoreRT Framework published to nuget
// Do Native Compilation // Do Native Compilation
var result = Command.Create($"dotnet-compile-native", $"--rsp \"{rsp}\"") var result = Command.Create("dotnet-compile-native", $"--rsp \"{rsp}\"")
.ForwardStdErr() .ForwardStdErr()
.ForwardStdOut() .ForwardStdOut()
.Execute(); .Execute();