dotnet-compile-native
Supports IL to Native compilation on Windows using CPP and RyuJit Code Generators. Supports RyuJit Code generation on Linux.
This commit is contained in:
parent
a492ea7834
commit
da8bd2a6f6
16 changed files with 1520 additions and 0 deletions
64
src/Microsoft.DotNet.Tools.Compiler.Native/Config.cs
Normal file
64
src/Microsoft.DotNet.Tools.Compiler.Native/Config.cs
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Microsoft.DotNet.Tools.Compiler.Native
|
||||||
|
{
|
||||||
|
public class Config
|
||||||
|
{
|
||||||
|
public string LogPath { get; set; }
|
||||||
|
public string InputManagedAssemblyPath { get; set; }
|
||||||
|
|
||||||
|
public string OutputDirectory { get; set; }
|
||||||
|
public string IntermediateDirectory { get; set; }
|
||||||
|
|
||||||
|
public BuildConfiguration BuildType { get; set; }
|
||||||
|
public ArchitectureMode Architecture { get; set; }
|
||||||
|
public NativeIntermediateMode NativeMode { get; set; }
|
||||||
|
public OSMode OS { get; set; }
|
||||||
|
|
||||||
|
public List<string> ReferencePaths { get; set; }
|
||||||
|
|
||||||
|
// Optional Customization Points (Can be null)
|
||||||
|
public string IlcArgs { get; set; }
|
||||||
|
public List<string> LinkLibPaths { get; set; }
|
||||||
|
|
||||||
|
// Required Customization Points (Must have default)
|
||||||
|
public string AppDepSDKPath { get; set; }
|
||||||
|
public string ILToNativePath { get; set; }
|
||||||
|
public string RuntimeLibPath { get; set; }
|
||||||
|
|
||||||
|
public Config()
|
||||||
|
{
|
||||||
|
LinkLibPaths = new List<string>();
|
||||||
|
ReferencePaths = new List<string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum NativeIntermediateMode
|
||||||
|
{
|
||||||
|
cpp,
|
||||||
|
ryujit,
|
||||||
|
custom
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ArchitectureMode
|
||||||
|
{
|
||||||
|
x86,
|
||||||
|
x64
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum OSMode
|
||||||
|
{
|
||||||
|
Linux,
|
||||||
|
Windows,
|
||||||
|
Mac
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum BuildConfiguration
|
||||||
|
{
|
||||||
|
debug,
|
||||||
|
release
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
124
src/Microsoft.DotNet.Tools.Compiler.Native/Helpers.cs
Normal file
124
src/Microsoft.DotNet.Tools.Compiler.Native/Helpers.cs
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
using Microsoft.Dnx.Runtime.Common.CommandLine;
|
||||||
|
using Microsoft.DotNet.Cli.Utils;
|
||||||
|
using Microsoft.DotNet.Tools.Common;
|
||||||
|
|
||||||
|
namespace Microsoft.DotNet.Tools.Compiler.Native
|
||||||
|
{
|
||||||
|
public static class Helpers
|
||||||
|
{
|
||||||
|
internal static T ParseEnum<T>(string value)
|
||||||
|
{
|
||||||
|
return (T)Enum.Parse(typeof(T), value, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void CleanOrCreateDirectory(string path)
|
||||||
|
{
|
||||||
|
if (Directory.Exists(path))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Directory.Delete(path, recursive: true);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Unable to remove directory: " + path);
|
||||||
|
Console.WriteLine(e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Directory.CreateDirectory(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static ArchitectureMode GetCurrentArchitecture()
|
||||||
|
{
|
||||||
|
// TODO Support Architectures other than x64
|
||||||
|
return ArchitectureMode.x64;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static OSMode GetCurrentOS()
|
||||||
|
{
|
||||||
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
|
{
|
||||||
|
return OSMode.Windows;
|
||||||
|
}
|
||||||
|
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
|
||||||
|
{
|
||||||
|
return OSMode.Mac;
|
||||||
|
}
|
||||||
|
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||||
|
{
|
||||||
|
return OSMode.Linux;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception("Unrecognized OS. dotnet-compile-native is compatible with Windows, OSX, and Linux");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
internal static IEnumerable<string> SplitStringCommandLine(string commandLine)
|
||||||
|
{
|
||||||
|
bool inQuotes = false;
|
||||||
|
|
||||||
|
return commandLine.Split(c =>
|
||||||
|
{
|
||||||
|
if (c == '\"')
|
||||||
|
inQuotes = !inQuotes;
|
||||||
|
|
||||||
|
return !inQuotes && c == ' ';
|
||||||
|
})
|
||||||
|
.Select(arg => arg.Trim().TrimMatchingQuotes('\"'))
|
||||||
|
.Where(arg => !string.IsNullOrEmpty(arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string TrimMatchingQuotes(this string input, char quote)
|
||||||
|
{
|
||||||
|
if ((input.Length >= 2) &&
|
||||||
|
(input[0] == quote) && (input[input.Length - 1] == quote))
|
||||||
|
return input.Substring(1, input.Length - 2);
|
||||||
|
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<string> Split(this string str,
|
||||||
|
Func<char, bool> controller)
|
||||||
|
{
|
||||||
|
int nextPiece = 0;
|
||||||
|
|
||||||
|
for (int c = 0; c < str.Length; c++)
|
||||||
|
{
|
||||||
|
if (controller(str[c]))
|
||||||
|
{
|
||||||
|
yield return str.Substring(nextPiece, c - nextPiece);
|
||||||
|
nextPiece = c + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
yield return str.Substring(nextPiece);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
internal class ArgValues
|
||||||
|
{
|
||||||
|
public string LogPath { get; set; }
|
||||||
|
public string InputManagedAssemblyPath { get; set; }
|
||||||
|
public string OutputDirectory { get; set; }
|
||||||
|
public string IntermediateDirectory { get; set; }
|
||||||
|
public string BuildType { get; set; }
|
||||||
|
public string Architecture { get; set; }
|
||||||
|
public string NativeMode { get; set; }
|
||||||
|
public List<string> ReferencePaths { get; set; }
|
||||||
|
public string IlcArgs { get; set; }
|
||||||
|
public List<string> LinkLibPaths { get; set; }
|
||||||
|
public string AppDepSDKPath { get; set; }
|
||||||
|
public string ILToNativePath { get; set; }
|
||||||
|
public string RuntimeLibPath { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
106
src/Microsoft.DotNet.Tools.Compiler.Native/ILCompilerInvoker.cs
Normal file
106
src/Microsoft.DotNet.Tools.Compiler.Native/ILCompilerInvoker.cs
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
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 ILCompilerInvoker
|
||||||
|
{
|
||||||
|
//private readonly string ExecutableName = "ILToNative" + Constants.ExeSuffix;
|
||||||
|
private readonly string ExecutableName = "corerun" + Constants.ExeSuffix;
|
||||||
|
private readonly string ILCompiler = "ilc.exe";
|
||||||
|
|
||||||
|
private static readonly Dictionary<NativeIntermediateMode, string> ModeOutputExtensionMap = new Dictionary<NativeIntermediateMode, string>
|
||||||
|
{
|
||||||
|
{ NativeIntermediateMode.cpp, ".cpp" },
|
||||||
|
{ NativeIntermediateMode.ryujit, ".obj" }
|
||||||
|
};
|
||||||
|
|
||||||
|
private static readonly Dictionary<OSMode, string> OSCoreLibNameMap = new Dictionary<OSMode, string>()
|
||||||
|
{
|
||||||
|
{OSMode.Windows, "System.Private.CoreLib.dll" },
|
||||||
|
{OSMode.Linux, "System.Private.Corelib.dll" },
|
||||||
|
{OSMode.Mac, "System.Private.Corelib.dll" },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
private string ArgStr { get; set; }
|
||||||
|
|
||||||
|
public ILCompilerInvoker(Config config)
|
||||||
|
{
|
||||||
|
InitializeArgs(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitializeArgs(Config config)
|
||||||
|
{
|
||||||
|
var argsList = new List<string>();
|
||||||
|
|
||||||
|
var managedPath = Path.Combine(config.ILToNativePath, ILCompiler);
|
||||||
|
argsList.Add(managedPath);
|
||||||
|
|
||||||
|
// Input File
|
||||||
|
var inputFilePath = config.InputManagedAssemblyPath;
|
||||||
|
argsList.Add(inputFilePath);
|
||||||
|
|
||||||
|
// System.Private.CoreLib Reference
|
||||||
|
var coreLibPath = Path.Combine(config.ILToNativePath, OSCoreLibNameMap[config.OS]);
|
||||||
|
argsList.Add($"-r \"{coreLibPath}\"");
|
||||||
|
|
||||||
|
// Dependency References
|
||||||
|
foreach (var reference in config.ReferencePaths)
|
||||||
|
{
|
||||||
|
argsList.Add($"-r \"{reference}\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set Output DetermineOutFile
|
||||||
|
var outFile = DetermineOutputFile(config);
|
||||||
|
argsList.Add($"-out \"{outFile}\"");
|
||||||
|
|
||||||
|
// Add Mode Flag TODO
|
||||||
|
if (config.NativeMode == NativeIntermediateMode.cpp)
|
||||||
|
{
|
||||||
|
argsList.Add("-cpp");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Custom Ilc Args support
|
||||||
|
if (! string.IsNullOrEmpty(config.IlcArgs))
|
||||||
|
{
|
||||||
|
argsList.Add(config.IlcArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.ArgStr = string.Join(" ", argsList);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Invoke(Config config)
|
||||||
|
{
|
||||||
|
var executablePath = Path.Combine(config.ILToNativePath, ExecutableName);
|
||||||
|
|
||||||
|
var result = Command.Create(executablePath, ArgStr)
|
||||||
|
.ForwardStdErr()
|
||||||
|
.ForwardStdOut()
|
||||||
|
.Execute();
|
||||||
|
|
||||||
|
return result.ExitCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string DetermineOutputFile(Config config)
|
||||||
|
{
|
||||||
|
var intermediateDirectory = config.IntermediateDirectory;
|
||||||
|
|
||||||
|
var extension = ModeOutputExtensionMap[config.NativeMode];
|
||||||
|
|
||||||
|
var filename = Path.GetFileNameWithoutExtension(config.InputManagedAssemblyPath);
|
||||||
|
|
||||||
|
var outFile = Path.Combine(intermediateDirectory, filename + extension);
|
||||||
|
|
||||||
|
return outFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
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 interface IPlatformNativeStep
|
||||||
|
{
|
||||||
|
int Invoke(Config config);
|
||||||
|
string DetermineOutputFile(Config config);
|
||||||
|
bool CheckPreReqs();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,131 @@
|
||||||
|
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 IntermediateCompiler
|
||||||
|
{
|
||||||
|
public static IntermediateCompiler Create(Config config)
|
||||||
|
{
|
||||||
|
var platformStepList = CreatePlatformNativeSteps(config);
|
||||||
|
|
||||||
|
return new IntermediateCompiler(platformStepList);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<IPlatformNativeStep> CreatePlatformNativeSteps(Config config)
|
||||||
|
{
|
||||||
|
if (config.NativeMode == NativeIntermediateMode.cpp)
|
||||||
|
{
|
||||||
|
return CreateCppSteps(config);
|
||||||
|
}
|
||||||
|
else if (config.NativeMode == NativeIntermediateMode.ryujit)
|
||||||
|
{
|
||||||
|
return CreateJitSteps(config);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception("Unrecognized Mode");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<IPlatformNativeStep> CreateCppSteps(Config config)
|
||||||
|
{
|
||||||
|
var stepList = new List<IPlatformNativeStep>();
|
||||||
|
|
||||||
|
if (config.OS == OSMode.Windows)
|
||||||
|
{
|
||||||
|
stepList.Add(new WindowsCppCompileStep(config));
|
||||||
|
stepList.Add(new WindowsLinkStep(config));
|
||||||
|
}
|
||||||
|
else if (config.OS == OSMode.Linux)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("Linux Cpp not yet supported.");
|
||||||
|
}
|
||||||
|
else if (config.OS == OSMode.Mac)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("Mac not yet supported.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception("Unrecognized Operating System. Unable to create Intermediate Compiler.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return stepList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<IPlatformNativeStep> CreateJitSteps(Config config)
|
||||||
|
{
|
||||||
|
var stepList = new List<IPlatformNativeStep>();
|
||||||
|
|
||||||
|
if (config.OS == OSMode.Windows)
|
||||||
|
{
|
||||||
|
stepList.Add(new WindowsLinkStep(config));
|
||||||
|
}
|
||||||
|
else if (config.OS == OSMode.Linux)
|
||||||
|
{
|
||||||
|
stepList.Add(new LinuxRyuJitCompileStep(config));
|
||||||
|
}
|
||||||
|
else if (config.OS == OSMode.Mac)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("Mac RyuJit not supported");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception("Unrecognized Operating System. Unable to create Intermediate Compiler.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return stepList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<IPlatformNativeStep> StepList { get; set; }
|
||||||
|
|
||||||
|
private IntermediateCompiler(List<IPlatformNativeStep> stepList)
|
||||||
|
{
|
||||||
|
if (stepList == null || stepList.Count < 1)
|
||||||
|
{
|
||||||
|
throw new Exception("Intermediate step list must not be empty.");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.StepList = stepList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Invoke(Config config)
|
||||||
|
{
|
||||||
|
foreach(var step in StepList)
|
||||||
|
{
|
||||||
|
int result = step.Invoke(config);
|
||||||
|
|
||||||
|
if (result != 0)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string DetermineOutputFile(Config config)
|
||||||
|
{
|
||||||
|
return StepList.Last().DetermineOutputFile(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CheckPreReqs()
|
||||||
|
{
|
||||||
|
var check = true;
|
||||||
|
|
||||||
|
foreach(var step in StepList)
|
||||||
|
{
|
||||||
|
check = check && step.CheckPreReqs();
|
||||||
|
}
|
||||||
|
|
||||||
|
return check;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,129 @@
|
||||||
|
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 LinuxCppCompiler : IPlatformNativeStep
|
||||||
|
{
|
||||||
|
private readonly string CompilerName = "clang-3.5";
|
||||||
|
private readonly string InputExtension = ".cpp";
|
||||||
|
|
||||||
|
private readonly string CompilerOutputExtension = ".a";
|
||||||
|
|
||||||
|
// TODO: debug/release support
|
||||||
|
private readonly string cLibsFlags = "-lm -ldl";
|
||||||
|
private readonly string cflags = "-g -lstdc++ -lrt -Wno-invalid-offsetof -pthread";
|
||||||
|
|
||||||
|
private readonly string[] libs = new string[]
|
||||||
|
{
|
||||||
|
"System.Native.so",
|
||||||
|
"libPortableRuntime.a",
|
||||||
|
"libbootstrappercpp.a",
|
||||||
|
"libSystem.Private.CoreLib.Native.a",
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
private string CompilerArgStr { get; set; }
|
||||||
|
|
||||||
|
public LinuxCppCompiler(Config config)
|
||||||
|
{
|
||||||
|
InitializeArgs(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Invoke(Config config)
|
||||||
|
{
|
||||||
|
var result = InvokeCompiler(config);
|
||||||
|
if (result != 0)
|
||||||
|
{
|
||||||
|
Reporter.Error.WriteLine("Compilation of intermediate files failed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CheckPreReqs()
|
||||||
|
{
|
||||||
|
// TODO check for clang
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitializeArgs(Config config)
|
||||||
|
{
|
||||||
|
var argsList = new List<string>();
|
||||||
|
|
||||||
|
// Flags
|
||||||
|
argsList.Add(cflags);
|
||||||
|
|
||||||
|
// Add Includes
|
||||||
|
argsList.Add("-I");
|
||||||
|
argsList.Add(Path.Combine(config.AppDepSDKPath, "CPPSdk/ubuntu.14.04"));
|
||||||
|
|
||||||
|
argsList.Add("-I");
|
||||||
|
argsList.Add(Path.Combine(config.AppDepSDKPath, "CPPSdk"));
|
||||||
|
|
||||||
|
// Add Stubs
|
||||||
|
argsList.Add(Path.Combine(config.AppDepSDKPath, "CPPSdk/ubuntu.14.04/lxstubs.cpp"));
|
||||||
|
|
||||||
|
// Input File
|
||||||
|
var inCppFile = DetermineInFile(config);
|
||||||
|
argsList.Add(inCppFile);
|
||||||
|
|
||||||
|
// Libs
|
||||||
|
foreach (var lib in libs)
|
||||||
|
{
|
||||||
|
var libPath = Path.Combine(config.RuntimeLibPath, lib);
|
||||||
|
argsList.Add(libPath);
|
||||||
|
}
|
||||||
|
argsList.Add(cLibsFlags);
|
||||||
|
|
||||||
|
// Output
|
||||||
|
var libOut = DetermineOutputFile(config);
|
||||||
|
argsList.Add($"-o \"{libOut}\"");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
this.CompilerArgStr = string.Join(" ", argsList);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int InvokeCompiler(Config config)
|
||||||
|
{
|
||||||
|
var result = Command.Create(CompilerName, CompilerArgStr)
|
||||||
|
.ForwardStdErr()
|
||||||
|
.ForwardStdOut()
|
||||||
|
.Execute();
|
||||||
|
|
||||||
|
return result.ExitCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string DetermineInFile(Config config)
|
||||||
|
{
|
||||||
|
var intermediateDirectory = config.IntermediateDirectory;
|
||||||
|
|
||||||
|
var filename = Path.GetFileNameWithoutExtension(config.InputManagedAssemblyPath);
|
||||||
|
|
||||||
|
var infile = Path.Combine(intermediateDirectory, filename + InputExtension);
|
||||||
|
|
||||||
|
return infile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string DetermineOutputFile(Config config)
|
||||||
|
{
|
||||||
|
var inputFile = DetermineInFile(config);
|
||||||
|
|
||||||
|
return inputFile + CompilerOutputExtension;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool RequiresLinkStep()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,135 @@
|
||||||
|
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 LinuxRyuJitCompileStep : IPlatformNativeStep
|
||||||
|
{
|
||||||
|
private readonly string CompilerName = "clang-3.5";
|
||||||
|
private readonly string InputExtension = ".obj";
|
||||||
|
|
||||||
|
private readonly string CompilerOutputExtension = "";
|
||||||
|
|
||||||
|
// TODO: debug/release support
|
||||||
|
private readonly string cflags = "-lstdc++ -lpthread -ldl -lm";
|
||||||
|
|
||||||
|
private readonly string[] libs = new string[]
|
||||||
|
{
|
||||||
|
"libbootstrapper.a",
|
||||||
|
"libRuntime.a",
|
||||||
|
"libPortableRuntime.a",
|
||||||
|
"libSystem.Private.CoreLib.Native.a",
|
||||||
|
"System.Native.so"
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
private string CompilerArgStr { get; set; }
|
||||||
|
|
||||||
|
public LinuxRyuJitCompileStep(Config config)
|
||||||
|
{
|
||||||
|
InitializeArgs(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Invoke(Config config)
|
||||||
|
{
|
||||||
|
var result = InvokeCompiler(config);
|
||||||
|
if (result != 0)
|
||||||
|
{
|
||||||
|
Reporter.Error.WriteLine("Compilation of intermediate files failed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CheckPreReqs()
|
||||||
|
{
|
||||||
|
// TODO check for clang
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitializeArgs(Config config)
|
||||||
|
{
|
||||||
|
var argsList = new List<string>();
|
||||||
|
|
||||||
|
// Flags
|
||||||
|
argsList.Add(cflags);
|
||||||
|
|
||||||
|
// Input File
|
||||||
|
var inLibFile = DetermineInFile(config);
|
||||||
|
argsList.Add(inLibFile);
|
||||||
|
|
||||||
|
// Libs
|
||||||
|
foreach (var lib in libs)
|
||||||
|
{
|
||||||
|
var libPath = Path.Combine(config.RuntimeLibPath, lib);
|
||||||
|
argsList.Add(libPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output
|
||||||
|
var libOut = DetermineOutputFile(config);
|
||||||
|
argsList.Add($"-o \"{libOut}\"");
|
||||||
|
|
||||||
|
// Add Stubs
|
||||||
|
argsList.Add(Path.Combine(config.AppDepSDKPath, "CPPSdk/ubuntu.14.04/lxstubs.cpp"));
|
||||||
|
|
||||||
|
this.CompilerArgStr = string.Join(" ", argsList);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int InvokeCompiler(Config config)
|
||||||
|
{
|
||||||
|
var result = Command.Create(CompilerName, CompilerArgStr)
|
||||||
|
.ForwardStdErr()
|
||||||
|
.ForwardStdOut()
|
||||||
|
.Execute();
|
||||||
|
|
||||||
|
// Needs System.Native.so in output
|
||||||
|
var sharedLibPath = Path.Combine(config.ILToNativePath, "System.Native.so");
|
||||||
|
var outputSharedLibPath = Path.Combine(config.OutputDirectory, "System.Native.so");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
File.Copy(sharedLibPath, outputSharedLibPath);
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
Reporter.Error.WriteLine("Unable to copy System.Native.so to output");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.ExitCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string DetermineInFile(Config config)
|
||||||
|
{
|
||||||
|
var intermediateDirectory = config.IntermediateDirectory;
|
||||||
|
|
||||||
|
var filename = Path.GetFileNameWithoutExtension(config.InputManagedAssemblyPath);
|
||||||
|
|
||||||
|
var infile = Path.Combine(intermediateDirectory, filename + InputExtension);
|
||||||
|
|
||||||
|
return infile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string DetermineOutputFile(Config config)
|
||||||
|
{
|
||||||
|
var intermediateDirectory = config.OutputDirectory;
|
||||||
|
|
||||||
|
var filename = Path.GetFileNameWithoutExtension(config.InputManagedAssemblyPath);
|
||||||
|
|
||||||
|
var outfile = Path.Combine(intermediateDirectory, filename + CompilerOutputExtension);
|
||||||
|
|
||||||
|
return outfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool RequiresLinkStep()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
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 MacCppCompileStep : IPlatformNativeStep
|
||||||
|
{
|
||||||
|
public MacCppCompileStep(Config config)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("Mac Cpp Not Supported Yet");
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Invoke(Config config)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("mac cpp Not supported yet.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CheckPreReqs()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("mac cpp Not supported yet.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public string DetermineOutputFile(Config config)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("Mac cpp Not supported yet.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool RequiresLinkStep()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
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 MacLinkStep : IPlatformNativeStep
|
||||||
|
{
|
||||||
|
public int Invoke(Config config)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("Mac linker Not supported yet.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CheckPreReqs()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("Mac linker Not supported yet.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public string DetermineOutputFile(Config config)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("Mac linker Not supported yet.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.DotNet.Cli.Utils;
|
||||||
|
|
||||||
|
namespace Microsoft.DotNet.Tools.Compiler.Native
|
||||||
|
{
|
||||||
|
class WindowsCommon
|
||||||
|
{
|
||||||
|
internal static int SetVCVars()
|
||||||
|
{
|
||||||
|
// TODO: This is not working because it sets the environment variables in a child process
|
||||||
|
// For now get around this by using x86_amd64 cross tools
|
||||||
|
|
||||||
|
var commonToolsPath = Environment.GetEnvironmentVariable("VS140COMNTOOLS");
|
||||||
|
|
||||||
|
var scriptPath = Path.Combine(commonToolsPath, "..\\..\\VC\\vcvarsall.bat");
|
||||||
|
var scriptArgs = "x86_amd64";
|
||||||
|
|
||||||
|
var result = Command.Create(scriptPath, scriptArgs)
|
||||||
|
.ForwardStdErr()
|
||||||
|
.ForwardStdOut()
|
||||||
|
.Execute();
|
||||||
|
|
||||||
|
return result.ExitCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,124 @@
|
||||||
|
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 WindowsCppCompileStep : IPlatformNativeStep
|
||||||
|
{
|
||||||
|
//TODO support x86
|
||||||
|
private readonly string CompilerName = "cl.exe";
|
||||||
|
|
||||||
|
private readonly string VSBin = "..\\..\\VC\\bin\\x86_amd64";
|
||||||
|
private readonly string InputExtension = ".cpp";
|
||||||
|
|
||||||
|
private readonly string CompilerOutputExtension = ".obj";
|
||||||
|
|
||||||
|
private static readonly Dictionary<BuildConfiguration, string> ConfigurationCompilerOptionsMap = new Dictionary<BuildConfiguration, string>
|
||||||
|
{
|
||||||
|
{ BuildConfiguration.debug, "/ZI /nologo /W3 /WX- /sdl /Od /D CPPCODEGEN /D WIN32 /D _DEBUG /D _CONSOLE /D _LIB /D _UNICODE /D UNICODE /Gm /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Zc:inline /Gd /TP /wd4477 /errorReport:prompt" },
|
||||||
|
{ BuildConfiguration.release, "/Zi /nologo /W3 /WX- /sdl /O2 /Oi /GL /D CPPCODEGEN /D WIN32 /D NDEBUG /D _CONSOLE /D _LIB /D _UNICODE /D UNICODE /Gm- /EHsc /MD /GS /Gy /fp:precise /Zc:wchar_t /Zc:forScope /Zc:inline /Gd /TP /wd4477 /errorReport:prompt" }
|
||||||
|
};
|
||||||
|
|
||||||
|
private string CompilerArgStr { get; set; }
|
||||||
|
|
||||||
|
public WindowsCppCompileStep(Config config)
|
||||||
|
{
|
||||||
|
InitializeArgs(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Invoke(Config config)
|
||||||
|
{
|
||||||
|
var result = WindowsCommon.SetVCVars();
|
||||||
|
if (result != 0)
|
||||||
|
{
|
||||||
|
Reporter.Error.WriteLine("vcvarsall.bat invocation failed.");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = InvokeCompiler(config);
|
||||||
|
if (result != 0)
|
||||||
|
{
|
||||||
|
Reporter.Error.WriteLine("Compilation of intermediate files failed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CheckPreReqs()
|
||||||
|
{
|
||||||
|
var vcInstallDir = Environment.GetEnvironmentVariable("VS140COMNTOOLS");
|
||||||
|
return !string.IsNullOrEmpty(vcInstallDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitializeArgs(Config config)
|
||||||
|
{
|
||||||
|
var argsList = new List<string>();
|
||||||
|
|
||||||
|
// Use a Custom Link Step
|
||||||
|
argsList.Add("/c");
|
||||||
|
|
||||||
|
// Add Includes
|
||||||
|
argsList.Add("/I");
|
||||||
|
argsList.Add(Path.Combine(config.AppDepSDKPath, "CPPSdk\\Windows_NT"));
|
||||||
|
|
||||||
|
argsList.Add("/I");
|
||||||
|
argsList.Add(Path.Combine(config.AppDepSDKPath, "CPPSdk"));
|
||||||
|
|
||||||
|
// Configuration Based Compiler Options
|
||||||
|
argsList.Add(ConfigurationCompilerOptionsMap[config.BuildType]);
|
||||||
|
|
||||||
|
// Output
|
||||||
|
var objOut = DetermineOutputFile(config);
|
||||||
|
argsList.Add($"/Fo\"{objOut}\"");
|
||||||
|
|
||||||
|
// Input File
|
||||||
|
var inCppFile = DetermineInFile(config);
|
||||||
|
argsList.Add(inCppFile);
|
||||||
|
|
||||||
|
this.CompilerArgStr = string.Join(" ", argsList);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int InvokeCompiler(Config config)
|
||||||
|
{
|
||||||
|
var vcInstallDir = Environment.GetEnvironmentVariable("VS140COMNTOOLS");
|
||||||
|
var compilerPath = Path.Combine(vcInstallDir, VSBin, CompilerName);
|
||||||
|
|
||||||
|
var result = Command.Create(compilerPath, CompilerArgStr)
|
||||||
|
.ForwardStdErr()
|
||||||
|
.ForwardStdOut()
|
||||||
|
.Execute();
|
||||||
|
|
||||||
|
return result.ExitCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string DetermineInFile(Config config)
|
||||||
|
{
|
||||||
|
var intermediateDirectory = config.IntermediateDirectory;
|
||||||
|
|
||||||
|
var filename = Path.GetFileNameWithoutExtension(config.InputManagedAssemblyPath);
|
||||||
|
|
||||||
|
var infile = Path.Combine(intermediateDirectory, filename + InputExtension);
|
||||||
|
|
||||||
|
return infile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string DetermineOutputFile(Config config)
|
||||||
|
{
|
||||||
|
var intermediateDirectory = config.IntermediateDirectory;
|
||||||
|
|
||||||
|
var filename = Path.GetFileNameWithoutExtension(config.InputManagedAssemblyPath);
|
||||||
|
|
||||||
|
var outfile = Path.Combine(intermediateDirectory, filename + CompilerOutputExtension);
|
||||||
|
|
||||||
|
return outfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,146 @@
|
||||||
|
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";
|
||||||
|
private readonly string VSBin = "..\\..\\VC\\bin\\x86_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; }
|
||||||
|
|
||||||
|
public WindowsLinkStep(Config config)
|
||||||
|
{
|
||||||
|
InitializeArgs(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Invoke(Config config)
|
||||||
|
{
|
||||||
|
var result = WindowsCommon.SetVCVars();
|
||||||
|
if (result != 0)
|
||||||
|
{
|
||||||
|
Reporter.Error.WriteLine("vcvarsall.bat invocation failed.");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = InvokeLinker(config);
|
||||||
|
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(Config 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)
|
||||||
|
{
|
||||||
|
argsList.Add(Path.Combine(config.RuntimeLibPath, lib));
|
||||||
|
}
|
||||||
|
|
||||||
|
//arch
|
||||||
|
argsList.Add($"/MACHINE:{config.Architecture}");
|
||||||
|
|
||||||
|
//Input Obj file
|
||||||
|
var inputFile = DetermineInputFile(config);
|
||||||
|
argsList.Add($"\"{inputFile}\"");
|
||||||
|
|
||||||
|
this.ArgStr = string.Join(" ", argsList);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int InvokeLinker(Config config)
|
||||||
|
{
|
||||||
|
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(Config config)
|
||||||
|
{
|
||||||
|
var outputDirectory = config.OutputDirectory;
|
||||||
|
|
||||||
|
var filename = Path.GetFileNameWithoutExtension(config.InputManagedAssemblyPath);
|
||||||
|
|
||||||
|
var outFile = Path.Combine(outputDirectory, filename + LinkerOutputExtension);
|
||||||
|
|
||||||
|
return outFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string DetermineInputFile(Config config)
|
||||||
|
{
|
||||||
|
var intermediateDirectory = config.IntermediateDirectory;
|
||||||
|
|
||||||
|
var filename = Path.GetFileNameWithoutExtension(config.InputManagedAssemblyPath);
|
||||||
|
|
||||||
|
var infile = Path.Combine(intermediateDirectory, filename + InputExtension);
|
||||||
|
|
||||||
|
return infile;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
41
src/Microsoft.DotNet.Tools.Compiler.Native/NativeCompiler.cs
Normal file
41
src/Microsoft.DotNet.Tools.Compiler.Native/NativeCompiler.cs
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Microsoft.DotNet.Tools.Compiler.Native
|
||||||
|
{
|
||||||
|
public class NativeCompiler
|
||||||
|
{
|
||||||
|
public static NativeCompiler Create(Config config)
|
||||||
|
{
|
||||||
|
var invoker = new ILCompilerInvoker(config);
|
||||||
|
var intCompiler = IntermediateCompiler.Create(config);
|
||||||
|
|
||||||
|
var nc = new NativeCompiler()
|
||||||
|
{
|
||||||
|
invoker = invoker,
|
||||||
|
intermediateCompiler = intCompiler
|
||||||
|
};
|
||||||
|
|
||||||
|
return nc;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ILCompilerInvoker invoker;
|
||||||
|
private IntermediateCompiler intermediateCompiler;
|
||||||
|
|
||||||
|
public bool CompileToNative(Config config)
|
||||||
|
{
|
||||||
|
int result = invoker.Invoke(config);
|
||||||
|
if(result != 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = intermediateCompiler.Invoke(config);
|
||||||
|
if (result != 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
353
src/Microsoft.DotNet.Tools.Compiler.Native/Program.cs
Normal file
353
src/Microsoft.DotNet.Tools.Compiler.Native/Program.cs
Normal file
|
@ -0,0 +1,353 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
using Microsoft.Dnx.Runtime.Common.CommandLine;
|
||||||
|
using Microsoft.DotNet.Cli.Utils;
|
||||||
|
using Microsoft.DotNet.Tools.Common;
|
||||||
|
|
||||||
|
namespace Microsoft.DotNet.Tools.Compiler.Native
|
||||||
|
{
|
||||||
|
public class Program
|
||||||
|
{
|
||||||
|
public static int Main(string[] args)
|
||||||
|
{
|
||||||
|
DebugHelper.HandleDebugSwitch(ref args);
|
||||||
|
|
||||||
|
var app = SetupApp();
|
||||||
|
|
||||||
|
return ExecuteApp(app, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int ExecuteApp(CommandLineApplication app, string[] args)
|
||||||
|
{
|
||||||
|
// Support Response File
|
||||||
|
foreach(var arg in args)
|
||||||
|
{
|
||||||
|
if(arg.Contains(".rsp"))
|
||||||
|
{
|
||||||
|
args = ParseResponseFile(arg);
|
||||||
|
|
||||||
|
if (args == null)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return app.Execute(args);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
System.Console.WriteLine(ex);
|
||||||
|
#else
|
||||||
|
Reporter.Error.WriteLine(ex.Message);
|
||||||
|
#endif
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string[] ParseResponseFile(string rspPath)
|
||||||
|
{
|
||||||
|
if (!File.Exists(rspPath))
|
||||||
|
{
|
||||||
|
Reporter.Error.WriteLine("Invalid Response File Path");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
string content = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
content = File.ReadAllText(rspPath);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Reporter.Error.WriteLine("Unable to Read Response File");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
string[] nArgs = Helpers.SplitStringCommandLine(rspPath).ToArray();
|
||||||
|
return nArgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CommandLineApplication SetupApp()
|
||||||
|
{
|
||||||
|
var app = new CommandLineApplication();
|
||||||
|
app.Name = "dotnet compile native";
|
||||||
|
app.FullName = "IL to Native compiler";
|
||||||
|
app.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("--temp-output <OUTPUT_DIR>", "Directory for intermediate files.", CommandOptionType.SingleValue);
|
||||||
|
var archArg = app.Option("-a|--arch <ARCH>", "Architecture type to compile for, defaults to the arch of the machine.", CommandOptionType.SingleValue );
|
||||||
|
var buildTypeArg = app.Option("-c|--configuration <TYPE>", "debug/release build type. 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 iltonativePathArg = app.Option("--iltonative-path <ILTONATIVE>", "Use to plug in a custom built iltonative.exe", CommandOptionType.SingleValue);
|
||||||
|
var runtimeLibPathArg = app.Option("--runtimelib-path <LIB_PATH>", "Use to plug in custom runtime and bootstrapper libs.", 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);
|
||||||
|
|
||||||
|
// Use Response File
|
||||||
|
var responseFilePathArg = app.Option("--rsp <RSP_FILE>", "Compilation Response File", CommandOptionType.SingleValue);
|
||||||
|
|
||||||
|
app.OnExecute(() =>
|
||||||
|
{
|
||||||
|
var cmdLineArgs = new ArgValues()
|
||||||
|
{
|
||||||
|
InputManagedAssemblyPath = managedInputArg.Value,
|
||||||
|
OutputDirectory = outputArg.Value(),
|
||||||
|
IntermediateDirectory = intermediateArg.Value(),
|
||||||
|
Architecture = archArg.Value(),
|
||||||
|
BuildType = buildTypeArg.Value(),
|
||||||
|
NativeMode = modeArg.Value(),
|
||||||
|
ReferencePaths = referencesArg.Values,
|
||||||
|
IlcArgs = ilcArgs.Value(),
|
||||||
|
ILToNativePath = iltonativePathArg.Value(),
|
||||||
|
RuntimeLibPath = runtimeLibPathArg.Value(),
|
||||||
|
LinkLibPaths = linklibArg.Values,
|
||||||
|
AppDepSDKPath = appdepSDKPathArg.Value(),
|
||||||
|
LogPath = logpathArg.Value()
|
||||||
|
};
|
||||||
|
|
||||||
|
var config = ParseAndValidateArgs(cmdLineArgs);
|
||||||
|
|
||||||
|
Helpers.CleanOrCreateDirectory(config.OutputDirectory);
|
||||||
|
Helpers.CleanOrCreateDirectory(config.IntermediateDirectory);
|
||||||
|
|
||||||
|
var nativeCompiler = NativeCompiler.Create(config);
|
||||||
|
|
||||||
|
var result = nativeCompiler.CompileToNative(config);
|
||||||
|
|
||||||
|
return result ? 0 : 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
return app;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Config ParseAndValidateArgs(ArgValues args)
|
||||||
|
{
|
||||||
|
var config = new Config();
|
||||||
|
|
||||||
|
// Managed Input
|
||||||
|
if (string.IsNullOrEmpty(args.InputManagedAssemblyPath) || !File.Exists(args.InputManagedAssemblyPath))
|
||||||
|
{
|
||||||
|
//TODO make this message good
|
||||||
|
throw new Exception("Invalid Managed Assembly Argument.");
|
||||||
|
}
|
||||||
|
|
||||||
|
config.InputManagedAssemblyPath = Path.GetFullPath(args.InputManagedAssemblyPath);
|
||||||
|
|
||||||
|
// Architecture
|
||||||
|
if(string.IsNullOrEmpty(args.Architecture))
|
||||||
|
{
|
||||||
|
config.Architecture = Helpers.GetCurrentArchitecture();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
config.Architecture = Helpers.ParseEnum<ArchitectureMode>(args.Architecture.ToLower());
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw new Exception("Invalid Architecture Option.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BuildType
|
||||||
|
if(string.IsNullOrEmpty(args.BuildType))
|
||||||
|
{
|
||||||
|
config.BuildType = GetDefaultBuildType();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
config.BuildType = Helpers.ParseEnum<BuildConfiguration>(args.BuildType.ToLower());
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw new Exception("Invalid BuildType Option.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output
|
||||||
|
if(string.IsNullOrEmpty(args.OutputDirectory))
|
||||||
|
{
|
||||||
|
config.OutputDirectory = GetDefaultOutputDir(config);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
config.OutputDirectory = args.OutputDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Intermediate
|
||||||
|
if(string.IsNullOrEmpty(args.IntermediateDirectory))
|
||||||
|
{
|
||||||
|
config.IntermediateDirectory = GetDefaultIntermediateDir(config);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
config.IntermediateDirectory = args.IntermediateDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mode
|
||||||
|
if (string.IsNullOrEmpty(args.NativeMode))
|
||||||
|
{
|
||||||
|
config.NativeMode = GetDefaultNativeMode();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
config.NativeMode = Helpers.ParseEnum<NativeIntermediateMode>(args.NativeMode.ToLower());
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw new Exception("Invalid Mode Option.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AppDeps (TEMP)
|
||||||
|
if(!string.IsNullOrEmpty(args.AppDepSDKPath))
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(args.AppDepSDKPath))
|
||||||
|
{
|
||||||
|
throw new Exception("AppDepSDK Directory does not exist.");
|
||||||
|
}
|
||||||
|
|
||||||
|
config.AppDepSDKPath = args.AppDepSDKPath;
|
||||||
|
|
||||||
|
var reference = Path.Combine(config.AppDepSDKPath, "*.dll");
|
||||||
|
config.ReferencePaths.Add(reference);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
config.AppDepSDKPath = GetDefaultAppDepSDKPath();
|
||||||
|
|
||||||
|
var reference = Path.Combine(config.AppDepSDKPath, "*.dll");
|
||||||
|
config.ReferencePaths.Add(reference);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ILToNativePath
|
||||||
|
if (!string.IsNullOrEmpty(args.ILToNativePath))
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(args.ILToNativePath))
|
||||||
|
{
|
||||||
|
throw new Exception("ILToNative Directory does not exist.");
|
||||||
|
}
|
||||||
|
|
||||||
|
config.ILToNativePath = args.ILToNativePath;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
config.ILToNativePath = GetDefaultILToNativePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
// RuntimeLibPath
|
||||||
|
if (!string.IsNullOrEmpty(args.RuntimeLibPath))
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(args.RuntimeLibPath))
|
||||||
|
{
|
||||||
|
throw new Exception("RuntimeLib Directory does not exist.");
|
||||||
|
}
|
||||||
|
|
||||||
|
config.RuntimeLibPath = args.RuntimeLibPath;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
config.RuntimeLibPath = GetDefaultRuntimeLibPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
// logpath
|
||||||
|
if (!string.IsNullOrEmpty(args.LogPath))
|
||||||
|
{
|
||||||
|
config.LogPath = Path.GetFullPath(args.LogPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// CodeGenPath
|
||||||
|
if (!string.IsNullOrEmpty(args.IlcArgs))
|
||||||
|
{
|
||||||
|
config.IlcArgs = Path.GetFullPath(args.IlcArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reference Paths
|
||||||
|
foreach (var reference in args.ReferencePaths)
|
||||||
|
{
|
||||||
|
config.ReferencePaths.Add(Path.GetFullPath(reference));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Link Libs
|
||||||
|
foreach (var lib in args.LinkLibPaths)
|
||||||
|
{
|
||||||
|
config.LinkLibPaths.Add(Path.GetFullPath(lib));
|
||||||
|
}
|
||||||
|
|
||||||
|
// OS
|
||||||
|
config.OS = Helpers.GetCurrentOS();
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetDefaultOutputDir(Config config)
|
||||||
|
{
|
||||||
|
var dir = Path.Combine(Constants.BinDirectoryName, config.Architecture.ToString(), config.BuildType.ToString(), "native");
|
||||||
|
|
||||||
|
return Path.GetFullPath(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetDefaultIntermediateDir(Config config)
|
||||||
|
{
|
||||||
|
var dir = Path.Combine(Constants.ObjDirectoryName, config.Architecture.ToString(), config.BuildType.ToString(), "native");
|
||||||
|
|
||||||
|
return Path.GetFullPath(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BuildConfiguration GetDefaultBuildType()
|
||||||
|
{
|
||||||
|
return BuildConfiguration.debug;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static NativeIntermediateMode GetDefaultNativeMode()
|
||||||
|
{
|
||||||
|
return NativeIntermediateMode.ryujit;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetDefaultAppDepSDKPath()
|
||||||
|
{
|
||||||
|
var appRoot = AppContext.BaseDirectory;
|
||||||
|
|
||||||
|
var dir = Path.Combine(appRoot, "appdepsdk");
|
||||||
|
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetDefaultILToNativePath()
|
||||||
|
{
|
||||||
|
return AppContext.BaseDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetDefaultRuntimeLibPath()
|
||||||
|
{
|
||||||
|
return AppContext.BaseDirectory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
"name": "appdepsdk",
|
||||||
|
"version": "1.0.0-*",
|
||||||
|
"compilationOptions": {
|
||||||
|
"emitEntryPoint": true
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.DotNet.AppDep":"1.0.0-*"
|
||||||
|
},
|
||||||
|
"frameworks": {
|
||||||
|
"dnxcore50": { }
|
||||||
|
}
|
||||||
|
}
|
33
src/Microsoft.DotNet.Tools.Compiler.Native/project.json
Normal file
33
src/Microsoft.DotNet.Tools.Compiler.Native/project.json
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
{
|
||||||
|
"name": "dotnet-compile-native",
|
||||||
|
"version": "1.0.0-*",
|
||||||
|
"compilationOptions": {
|
||||||
|
"emitEntryPoint": true
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.NETCore.Platforms":"1.0.1-*",
|
||||||
|
"Microsoft.NETCore.Runtime": "1.0.1-*",
|
||||||
|
"System.Console": "4.0.0-*",
|
||||||
|
"System.Collections": "4.0.11-*",
|
||||||
|
"System.Linq": "4.0.1-*",
|
||||||
|
"System.Linq.Expressions": "4.0.1-*",
|
||||||
|
"System.Diagnostics.Process": "4.1.0-*",
|
||||||
|
"System.IO": "4.0.11-*",
|
||||||
|
"System.IO.FileSystem": "4.0.1-*",
|
||||||
|
"System.AppContext": "4.0.1-*",
|
||||||
|
"Microsoft.DotNet.Cli.Utils": {
|
||||||
|
"type": "build",
|
||||||
|
"version": "1.0.0-*"
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.CommandLineUtils.Sources": {
|
||||||
|
"type": "build",
|
||||||
|
"version": "1.0.0-*"
|
||||||
|
},
|
||||||
|
"Microsoft.DotNet.ILCompiler": "1.0.0-*",
|
||||||
|
"Microsoft.DotNet.ObjectWriter": "1.0.0-*",
|
||||||
|
"Microsoft.DotNet.RyuJit": "1.0.0-*"
|
||||||
|
},
|
||||||
|
"frameworks": {
|
||||||
|
"dnxcore50": { }
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue