+
+ static string GetAssemblerCommand (string sourceFile, string objectFile)
+ {
+ if (style == "windows") {
+ string additionalArguments = "";
+ var assembler = GetAssemblerCompiler ();
+ if (assembler.Name.Contains ("clang.exe"))
+ //Clang uses additional arguments.
+ additionalArguments = "-c -x assembler";
+
+ return String.Format ("\"{0}\" {1} -o {2} {3} ", assembler.Path, additionalArguments, objectFile, sourceFile);
+ } else {
+ return String.Format ("{0} -o {1} {2} ", GetEnv ("AS", "as"), objectFile, sourceFile);
+ }
+ }
+
+#region WindowsToolchainSupport
+
+ class StringVersionComparer : IComparer<string> {
+ public int Compare (string stringA, string stringB)
+ {
+ Version versionA;
+ Version versionB;
+
+ var versionAMatch = System.Text.RegularExpressions.Regex.Match (stringA, @"\d+(\.\d +) + ");
+ if (versionAMatch.Success)
+ stringA = versionAMatch.ToString ();
+
+ var versionBMatch = System.Text.RegularExpressions.Regex.Match (stringB, @"\d+(\.\d+)+");
+ if (versionBMatch.Success)
+ stringB = versionBMatch.ToString ();
+
+ if (Version.TryParse (stringA, out versionA) && Version.TryParse (stringB, out versionB))
+ return versionA.CompareTo (versionB);
+
+ return string.Compare (stringA, stringB, StringComparison.OrdinalIgnoreCase);
+ }
+ }
+
+ class InstalledSDKInfo {
+ public InstalledSDKInfo (string name, string version, string installationFolder)
+ {
+ this.Name = name;
+ this.Version = Version.Parse (version);
+ this.InstallationFolder = installationFolder;
+ this.IsSubVersion = false;
+ this.AdditionalSDKs = new List<InstalledSDKInfo> ();
+ }
+
+ public InstalledSDKInfo (string name, string version, string installationFolder, bool isSubVersion)
+ : this (name, version, installationFolder)
+ {
+ this.IsSubVersion = isSubVersion;
+ }
+
+ public InstalledSDKInfo (string name, string version, string installationFolder, bool isSubVersion, InstalledSDKInfo parentSDK)
+ : this (name, version, installationFolder, isSubVersion)
+ {
+ this.ParentSDK = parentSDK;
+ }
+
+ public string Name { get; set; }
+ public Version Version { get; set; }
+ public string InstallationFolder { get; set; }
+ public bool IsSubVersion { get; set; }
+ public List<InstalledSDKInfo> AdditionalSDKs { get; }
+ public InstalledSDKInfo ParentSDK { get; set; }
+ }
+
+ class ToolchainProgram {
+ public ToolchainProgram (string name, string path)
+ {
+ this.Name = name;
+ this.Path = path;
+ }
+
+ public ToolchainProgram (string name, string path, InstalledSDKInfo parentSDK)
+ : this (name, path)
+ {
+ this.ParentSDK = parentSDK;
+ }
+
+ public Func<string, string> QuoteArg = arg => "\"" + arg + "\"";
+ public string Name { get; set; }
+ public string Path { get; set; }
+ public InstalledSDKInfo ParentSDK { get; set; }
+ public bool IsVSToolChain { get { return (Name.Contains ("cl.exe") || Name.Contains ("lib.exe")); } }
+ public bool IsGCCToolChain { get { return !IsVSToolChain; } }
+ }
+
+ class SDKHelper {
+
+ protected Microsoft.Win32.RegistryKey GetToolchainRegistrySubKey (string subKey)
+ {
+ Microsoft.Win32.RegistryKey key = null;
+
+ if (Environment.Is64BitProcess) {
+ key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey (@"SOFTWARE\Wow6432Node" + subKey) ??
+ Microsoft.Win32.Registry.CurrentUser.OpenSubKey (@"SOFTWARE\Wow6432Node" + subKey);
+ }
+
+ if (key == null) {
+ key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey (@"SOFTWARE" + subKey) ??
+ Microsoft.Win32.Registry.CurrentUser.OpenSubKey (@"SOFTWARE" + subKey);
+ }
+
+ return key;
+ }
+ }
+
+ class WindowsSDKHelper : SDKHelper {
+
+ List<InstalledSDKInfo> installedWindowsSDKs;
+ List<InstalledSDKInfo> installedCRuntimeSDKs;
+ InstalledSDKInfo installedWindowsSDK;
+ InstalledSDKInfo installedCRuntimeSDK;
+
+ static WindowsSDKHelper singletonInstance = new WindowsSDKHelper ();
+ static public WindowsSDKHelper GetInstance ()
+ {
+ return singletonInstance;
+ }
+
+ Dictionary<string, string> GetInstalledWindowsKitRootFolders ()
+ {
+ var rootFolders = new Dictionary<string, string> ();
+
+ using (var subKey = GetToolchainRegistrySubKey (@"\Microsoft\Microsoft SDKs\Windows\")) {
+ if (subKey != null) {
+ foreach (var keyName in subKey.GetSubKeyNames ()) {
+ var keyNameIsVersion = System.Text.RegularExpressions.Regex.Match (keyName, @"\d+(\.\d+)+");
+ if (keyNameIsVersion.Success) {
+ var installFolder = (string)Microsoft.Win32.Registry.GetValue (subKey.ToString () + @"\" + keyName, "InstallationFolder", "");
+ if (!rootFolders.ContainsKey (installFolder))
+ rootFolders.Add (installFolder, keyNameIsVersion.ToString ());
+ }
+ }
+ }
+ }
+
+ using (var subKey = GetToolchainRegistrySubKey (@"\Microsoft\Windows Kits\Installed Roots")) {
+ if (subKey != null) {
+ foreach (var valueName in subKey.GetValueNames ()) {
+ var valueNameIsKitsRoot = System.Text.RegularExpressions.Regex.Match (valueName, @"KitsRoot\d*");
+ if (valueNameIsKitsRoot.Success) {
+ var installFolder = (string)Microsoft.Win32.Registry.GetValue (subKey.ToString (), valueName, "");
+ if (!rootFolders.ContainsKey (installFolder)) {
+ var valueNameIsVersion = System.Text.RegularExpressions.Regex.Match (valueName, @"\d+(\.*\d+)+");
+ if (valueNameIsVersion.Success)
+ rootFolders.Add (installFolder, valueNameIsVersion.ToString ());
+ else
+ rootFolders.Add (installFolder, "");
+ }
+ }
+ }
+ }
+ }
+
+ return rootFolders;
+ }
+
+ void InitializeInstalledWindowsKits ()
+ {
+ if (installedWindowsSDKs == null && installedCRuntimeSDKs == null) {
+ List<InstalledSDKInfo> windowsSDKs = new List<InstalledSDKInfo> ();
+ List<InstalledSDKInfo> cRuntimeSDKs = new List<InstalledSDKInfo> ();
+ var rootFolders = GetInstalledWindowsKitRootFolders ();
+ foreach (var winKitRoot in rootFolders) {
+ // Try to locate Windows and CRuntime SDKs.
+ string winKitRootDir = winKitRoot.Key;
+ string winKitRootVersion = winKitRoot.Value;
+ string winKitIncludeDir = Path.Combine (winKitRootDir, "include");
+
+ //Search for installed SDK versions.
+ if (Directory.Exists (winKitIncludeDir)) {
+ var winKitIncludeDirInfo = new DirectoryInfo (winKitIncludeDir);
+ var versions = winKitIncludeDirInfo.GetDirectories (
+ "*.*", SearchOption.TopDirectoryOnly).OrderByDescending (p => p.Name, new StringVersionComparer ());
+
+ foreach (var version in versions) {
+ string versionedWindowsSDKHeaderPath = Path.Combine (version.FullName, "um", "windows.h");
+ string versionedCRuntimeSDKHeaderPath = Path.Combine (version.FullName, "ucrt", "stdlib.h");
+ var hasSubVersion = System.Text.RegularExpressions.Regex.Match (version.Name, @"\d+(\.\d+)+");
+ if (hasSubVersion.Success) {
+ if (File.Exists (versionedWindowsSDKHeaderPath))
+ //Found a specific Windows SDK sub version.
+ windowsSDKs.Add (new InstalledSDKInfo ("WindowsSDK", hasSubVersion.ToString (), winKitRootDir, true));
+ if (File.Exists (versionedCRuntimeSDKHeaderPath))
+ //Found a specific CRuntime SDK sub version.
+ cRuntimeSDKs.Add (new InstalledSDKInfo ("CRuntimeSDK", hasSubVersion.ToString (), winKitRootDir, true));
+ }
+ }
+ }
+
+ // Try to find SDK without specific sub version.
+ string windowsSDKHeaderPath = Path.Combine (winKitIncludeDir, "um", "windows.h");
+ if (File.Exists (windowsSDKHeaderPath))
+ //Found a Windows SDK version.
+ windowsSDKs.Add (new InstalledSDKInfo ("WindowsSDK", winKitRootVersion, winKitRootDir, false));
+
+ string cRuntimeSDKHeaderPath = Path.Combine (winKitIncludeDir, "ucrt", "stdlib.h");
+ if (File.Exists (cRuntimeSDKHeaderPath))
+ //Found a CRuntime SDK version.
+ cRuntimeSDKs.Add (new InstalledSDKInfo ("CRuntimeSDK", winKitRootVersion, winKitRootDir, false));
+ }
+
+ // Sort based on version.
+ windowsSDKs = windowsSDKs.OrderByDescending (p => p.Version.ToString (), new StringVersionComparer ()).ToList ();
+ cRuntimeSDKs = cRuntimeSDKs.OrderByDescending (p => p.Version.ToString (), new StringVersionComparer ()).ToList ();
+
+ installedWindowsSDKs = windowsSDKs;
+ installedCRuntimeSDKs = cRuntimeSDKs;
+
+ if (!quiet && installedWindowsSDKs != null) {
+ Console.WriteLine ("--- Windows SDK's ---");
+ foreach (var windowsSDK in installedWindowsSDKs) {
+ Console.WriteLine ("Path: " + windowsSDK.InstallationFolder);
+ Console.WriteLine ("Version: " + windowsSDK.Version);
+ }
+ Console.WriteLine ("---------------");
+ }
+
+ if (!quiet && installedCRuntimeSDKs != null) {
+ Console.WriteLine ("--- C-Runtime SDK's ---");
+ foreach (var cRuntimeSDK in installedCRuntimeSDKs) {
+ Console.WriteLine ("Path: " + cRuntimeSDK.InstallationFolder);
+ Console.WriteLine ("Version: " + cRuntimeSDK.Version);
+ if (cRuntimeSDK.ParentSDK != null) {
+ Console.WriteLine ("Parent SDK Path: " + cRuntimeSDK.ParentSDK.InstallationFolder);
+ Console.WriteLine ("Parent SDK Version: " + cRuntimeSDK.ParentSDK.Version);
+ }
+ }
+ Console.WriteLine ("---------------");
+ }
+ }
+
+ return;
+ }
+
+ List<InstalledSDKInfo> GetInstalledWindowsSDKs ()
+ {
+ if (installedWindowsSDKs == null)
+ InitializeInstalledWindowsKits ();
+
+ return installedWindowsSDKs;
+ }
+
+ List<InstalledSDKInfo> GetInstalledCRuntimeSDKs ()
+ {
+ if (installedCRuntimeSDKs == null)
+ InitializeInstalledWindowsKits ();
+
+ return installedCRuntimeSDKs;
+ }
+
+ InstalledSDKInfo GetInstalledWindowsSDK ()
+ {
+ if (installedWindowsSDK == null) {
+ string winSDKDir = "";
+ InstalledSDKInfo windowsSDK = null;
+ List<InstalledSDKInfo> windowsSDKs = GetInstalledWindowsSDKs ();
+
+ // Check that env doesn't already include needed values.
+ winSDKDir = GetEnv ("WINSDK", "");
+ if (winSDKDir.Length == 0)
+ // If executed from a VS developer command prompt, SDK dir set in env.
+ winSDKDir = GetEnv ("WindowsSdkDir", "");
+
+ // Check that env doesn't already include needed values.
+ // If executed from a VS developer command prompt, SDK version set in env.
+ var winSDKVersion = System.Text.RegularExpressions.Regex.Match (GetEnv ("WindowsSdkVersion", ""), @"\d+(\.\d+)+");
+
+ if (winSDKDir.Length != 0 && windowsSDKs != null) {
+ // Find installed SDK based on requested info.
+ if (winSDKVersion.Success)
+ windowsSDK = windowsSDKs.Find (x => (x.InstallationFolder == winSDKDir && x.Version.ToString () == winSDKVersion.ToString ()));
+ else
+ windowsSDK = windowsSDKs.Find (x => x.InstallationFolder == winSDKDir);
+ }
+
+ if (windowsSDK == null && winSDKVersion.Success && windowsSDKs != null)
+ // Find installed SDK based on requested info.
+ windowsSDK = windowsSDKs.Find (x => x.Version.ToString () == winSDKVersion.ToString ());
+
+ if (windowsSDK == null && windowsSDKs != null)
+ // Get latest installed verison.
+ windowsSDK = windowsSDKs.First ();
+
+ installedWindowsSDK = windowsSDK;
+ }
+
+ return installedWindowsSDK;
+ }
+
+ string FindCRuntimeSDKIncludePath (InstalledSDKInfo sdk)
+ {
+ string cRuntimeIncludePath = Path.Combine (sdk.InstallationFolder, "include");
+ if (sdk.IsSubVersion)
+ cRuntimeIncludePath = Path.Combine (cRuntimeIncludePath, sdk.Version.ToString ());
+
+ cRuntimeIncludePath = Path.Combine (cRuntimeIncludePath, "ucrt");
+ if (!Directory.Exists (cRuntimeIncludePath))
+ cRuntimeIncludePath = "";
+
+ return cRuntimeIncludePath;
+ }
+
+ string FindCRuntimeSDKLibPath (InstalledSDKInfo sdk)
+ {
+ string cRuntimeLibPath = Path.Combine (sdk.InstallationFolder, "lib");
+ if (sdk.IsSubVersion)
+ cRuntimeLibPath = Path.Combine (cRuntimeLibPath, sdk.Version.ToString ());
+
+ cRuntimeLibPath = Path.Combine (cRuntimeLibPath, "ucrt", Target64BitApplication () ? "x64" : "x86");
+ if (!Directory.Exists (cRuntimeLibPath))
+ cRuntimeLibPath = "";
+
+ return cRuntimeLibPath;
+ }
+
+ InstalledSDKInfo GetInstalledCRuntimeSDK ()
+ {
+ if (installedCRuntimeSDK == null) {
+ InstalledSDKInfo cRuntimeSDK = null;
+ var windowsSDK = GetInstalledWindowsSDK ();
+ var cRuntimeSDKs = GetInstalledCRuntimeSDKs ();
+
+ if (windowsSDK != null && cRuntimeSDKs != null) {
+ cRuntimeSDK = cRuntimeSDKs.Find (x => x.Version.ToString () == windowsSDK.Version.ToString ());
+ if (cRuntimeSDK == null && cRuntimeSDKs.Count != 0)
+ cRuntimeSDK = cRuntimeSDKs.First ();
+
+ installedCRuntimeSDK = cRuntimeSDK;
+ }
+ }
+
+ return installedCRuntimeSDK;
+ }
+
+ public void AddWindowsSDKIncludePaths (List<string> includePaths)
+ {
+ InstalledSDKInfo winSDK = GetInstalledWindowsSDK ();
+ if (winSDK != null) {
+ string winSDKIncludeDir = Path.Combine (winSDK.InstallationFolder, "include");
+
+ if (winSDK.IsSubVersion)
+ winSDKIncludeDir = Path.Combine (winSDKIncludeDir, winSDK.Version.ToString ());
+
+ // Include sub folders.
+ if (Directory.Exists (winSDKIncludeDir)) {
+ includePaths.Add (Path.Combine (winSDKIncludeDir, "um"));
+ includePaths.Add (Path.Combine (winSDKIncludeDir, "shared"));
+ includePaths.Add (Path.Combine (winSDKIncludeDir, "winrt"));
+ }
+ }
+
+ return;
+ }
+
+ public void AddWindowsSDKLibPaths (List<string> libPaths)
+ {
+ InstalledSDKInfo winSDK = GetInstalledWindowsSDK ();
+ if (winSDK != null) {
+ string winSDKLibDir = Path.Combine (winSDK.InstallationFolder, "lib");
+
+ if (winSDK.IsSubVersion) {
+ winSDKLibDir = Path.Combine (winSDKLibDir, winSDK.Version.ToString ());
+ } else {
+ // Older WinSDK's header folders are not versioned, but installed libraries are, use latest availalble version for now.
+ var winSDKLibDirInfo = new DirectoryInfo (winSDKLibDir);
+ var versions = winSDKLibDirInfo.GetDirectories ("*.*", SearchOption.TopDirectoryOnly).OrderByDescending (p => p.Name, new StringVersionComparer ());
+ if (versions != null && versions.First () != null)
+ winSDKLibDir = versions.First ().FullName;
+ }
+
+ //Enumerat lib sub folders.
+ if (Directory.Exists (winSDKLibDir))
+ libPaths.Add (Path.Combine (winSDKLibDir, "um", Target64BitApplication () ? "x64" : "x86"));
+ }
+
+ return;
+ }
+
+ public void AddCRuntimeSDKIncludePaths (List<string> includePaths)
+ {
+ InstalledSDKInfo cRuntimeSDK = GetInstalledCRuntimeSDK ();
+ if (cRuntimeSDK != null) {
+ string cRuntimeSDKIncludeDir = FindCRuntimeSDKIncludePath (cRuntimeSDK);
+
+ if (cRuntimeSDKIncludeDir.Length != 0)
+ includePaths.Add (cRuntimeSDKIncludeDir);
+ }
+
+ return;
+ }
+
+ public void AddCRuntimeSDKLibPaths (List<string> libPaths)
+ {
+ InstalledSDKInfo cRuntimeSDK = GetInstalledCRuntimeSDK ();
+ if (cRuntimeSDK != null) {
+ string cRuntimeSDKLibDir = FindCRuntimeSDKLibPath (cRuntimeSDK);
+
+ if (cRuntimeSDKLibDir.Length != 0)
+ libPaths.Add (cRuntimeSDKLibDir);
+ }
+
+ return;
+ }
+ }
+
+ class VisualStudioSDKHelper : SDKHelper {
+
+ List<InstalledSDKInfo> installedVisualStudioSDKs;
+ InstalledSDKInfo installedVisualStudioSDK;
+
+ static VisualStudioSDKHelper singletonInstance = new VisualStudioSDKHelper ();
+ static public VisualStudioSDKHelper GetInstance ()
+ {
+ return singletonInstance;
+ }
+
+ List<InstalledSDKInfo> InitializeInstalledVisualStudioSDKs ()
+ {
+ if (installedVisualStudioSDKs == null) {
+ List<InstalledSDKInfo> sdks = new List<InstalledSDKInfo> ();
+
+ using (var subKey = GetToolchainRegistrySubKey (@"\Microsoft\VisualStudio\SxS\VS7")) {
+ if (subKey != null) {
+ foreach (var keyName in subKey.GetValueNames ()) {
+ var vsInstalltionFolder = (string)Microsoft.Win32.Registry.GetValue (subKey.ToString (), keyName, "");
+ if (Directory.Exists (vsInstalltionFolder)) {
+ var vsSDK = new InstalledSDKInfo ("VisualStudio", keyName, vsInstalltionFolder, false);
+ var vcInstallationFolder = Path.Combine (vsInstalltionFolder, "VC");
+
+ if (Directory.Exists (vcInstallationFolder))
+ vsSDK.AdditionalSDKs.Add (new InstalledSDKInfo ("VisualStudioVC", keyName, vcInstallationFolder, false, vsSDK));
+
+ sdks.Add (vsSDK);
+ }
+ }
+ }
+ }
+
+ // TODO: Add VS15 SetupConfiguration support.
+ // To reduce dependecies use vswhere.exe, if available.
+
+ // Sort based on version.
+ sdks = sdks.OrderByDescending (p => p.Version.ToString (), new StringVersionComparer ()).ToList ();
+ installedVisualStudioSDKs = sdks;
+ }
+
+ return installedVisualStudioSDKs;
+ }
+
+ string FindVisualStudioVCFolderPath (InstalledSDKInfo vcSDK, string subPath)
+ {
+ string folderPath = "";
+ if (vcSDK != null && vcSDK.ParentSDK != null) {
+ if (IsVisualStudio12 (vcSDK.ParentSDK) || IsVisualStudio14 (vcSDK.ParentSDK)) {
+ folderPath = Path.Combine (vcSDK.InstallationFolder, subPath);
+ } else if (IsVisualStudio15 (vcSDK.ParentSDK)) {
+ string msvcVersionPath = Path.Combine (vcSDK.InstallationFolder, "Tools", "MSVC");
+
+ // Add latest found version of MSVC toolchain.
+ if (Directory.Exists (msvcVersionPath)) {
+ var msvcVersionDirInfo = new DirectoryInfo (msvcVersionPath);
+ var versions = msvcVersionDirInfo.GetDirectories ("*.*", SearchOption.TopDirectoryOnly).OrderByDescending (p => p.Name, new StringVersionComparer ());
+
+ foreach (var version in versions) {
+ msvcVersionPath = Path.Combine (version.FullName, subPath);
+ if (Directory.Exists (msvcVersionPath)) {
+ folderPath = msvcVersionPath;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return folderPath;
+ }
+
+ string FindVisualStudioVCLibSubPath (InstalledSDKInfo vcSDK)
+ {
+ string subPath = "";
+
+ if (vcSDK != null && vcSDK.ParentSDK != null) {
+ if (IsVisualStudio12 (vcSDK.ParentSDK) || IsVisualStudio14 (vcSDK.ParentSDK))
+ subPath = Target64BitApplication () ? @"lib\amd64" : "lib";
+ else if (IsVisualStudio15 (vcSDK.ParentSDK))
+ subPath = Target64BitApplication () ? @"lib\x64" : @"lib\x86";
+ }
+
+ return subPath;
+ }
+
+ public InstalledSDKInfo GetInstalledVisualStudioSDK ()
+ {
+ if (installedVisualStudioSDK == null) {
+ List<InstalledSDKInfo> visualStudioSDKs = InitializeInstalledVisualStudioSDKs ();
+ InstalledSDKInfo visualStudioSDK = null;
+
+ // Check that env doesn't already include needed values.
+ // If executed from a VS developer command prompt, Visual Studio install dir set in env.
+ string vsVersion = GetEnv ("VisualStudioVersion", "");
+
+ if (vsVersion.Length != 0 && visualStudioSDKs != null)
+ // Find installed SDK based on requested info.
+ visualStudioSDK = visualStudioSDKs.Find (x => x.Version.ToString () == vsVersion);
+
+ if (visualStudioSDK == null && visualStudioSDKs != null)
+ // Get latest installed verison.
+ visualStudioSDK = visualStudioSDKs.First ();
+
+ installedVisualStudioSDK = visualStudioSDK;
+ }
+
+ return installedVisualStudioSDK;
+ }
+
+ public InstalledSDKInfo GetInstalledVisualStudioVCSDK ()
+ {
+ InstalledSDKInfo visualStudioVCSDK = null;
+
+ // Check that env doesn't already include needed values.
+ // If executed from a VS developer command prompt, Visual Studio install dir set in env.
+ string vcInstallDir = GetEnv ("VCINSTALLDIR", "");
+ if (vcInstallDir.Length != 0) {
+ List<InstalledSDKInfo> installedVisualStudioSDKs = InitializeInstalledVisualStudioSDKs ();
+ if (installedVisualStudioSDKs != null) {
+ foreach (var currentInstalledSDK in installedVisualStudioSDKs) {
+ // Find installed SDK based on requested info.
+ visualStudioVCSDK = currentInstalledSDK.AdditionalSDKs.Find (x => x.InstallationFolder == vcInstallDir);
+ if (visualStudioVCSDK != null)
+ break;
+ }
+ }
+ }
+
+ // Get latest installed VS VC SDK version.
+ if (visualStudioVCSDK == null) {
+ var visualStudioSDK = GetInstalledVisualStudioSDK ();
+ if (visualStudioSDK != null)
+ visualStudioVCSDK = visualStudioSDK.AdditionalSDKs.Find (x => x.Name == "VisualStudioVC");
+ }
+
+ return visualStudioVCSDK;
+ }
+
+ public bool IsVisualStudio12 (InstalledSDKInfo vsSDK)
+ {
+ return vsSDK.Version.Major == 12 || vsSDK.Version.Major == 2013;
+ }
+
+ public bool IsVisualStudio14 (InstalledSDKInfo vsSDK)
+ {
+ return vsSDK.Version.Major == 14 || vsSDK.Version.Major == 2015;
+ }
+
+ public bool IsVisualStudio15 (InstalledSDKInfo vsSDK)
+ {
+ return vsSDK.Version.Major == 15 || vsSDK.Version.Major == 2017;
+ }
+
+ public void AddVisualStudioVCIncludePaths (List<string> includePaths)
+ {
+ // Check that env doesn't already include needed values.
+ string vcIncludeDir = GetEnv ("VSINCLUDE", "");
+ if (vcIncludeDir.Length == 0) {
+ var visualStudioVCSDK = GetInstalledVisualStudioVCSDK ();
+ vcIncludeDir = FindVisualStudioVCFolderPath (visualStudioVCSDK, "include");
+ }
+
+ if (vcIncludeDir.Length != 0)
+ includePaths.Add (vcIncludeDir);
+
+ return;
+ }
+
+ public void AddVisualStudioVCLibPaths (List<string> libPaths)
+ {
+ // Check that env doesn't already include needed values.
+ string vcLibDir = GetEnv ("VSLIB", "");
+ if (vcLibDir.Length == 0) {
+ var vcSDK = GetInstalledVisualStudioVCSDK ();
+ vcLibDir = FindVisualStudioVCFolderPath (vcSDK, FindVisualStudioVCLibSubPath (vcSDK));
+ }
+
+ if (vcLibDir.Length != 0)
+ libPaths.Add (vcLibDir);
+
+ return;
+ }
+ }
+
+ class VCToolchainProgram {
+
+ protected ToolchainProgram toolchain;
+ public virtual bool IsVersion (InstalledSDKInfo vcSDK) { return false; }
+ public virtual ToolchainProgram FindVCToolchainProgram (InstalledSDKInfo vcSDK) { return null; }
+ }
+
+ class VC12ToolchainProgram : VCToolchainProgram {
+
+ public override bool IsVersion (InstalledSDKInfo vcSDK)
+ {
+ return VisualStudioSDKHelper.GetInstance ().IsVisualStudio12 (vcSDK);
+ }
+
+ protected ToolchainProgram FindVCToolchainProgram (string tool, InstalledSDKInfo vcSDK)
+ {
+ if (toolchain == null) {
+ string toolPath = "";
+ if (!string.IsNullOrEmpty (vcSDK?.InstallationFolder)) {
+ if (Target64BitApplication ())
+ toolPath = Path.Combine (new string [] { vcSDK.InstallationFolder, "bin", "amd64", tool });
+ else
+ toolPath = Path.Combine (new string [] { vcSDK.InstallationFolder, "bin", tool });
+
+ if (!File.Exists (toolPath))
+ toolPath = "";
+ }
+
+ toolchain = new ToolchainProgram (tool, toolPath, vcSDK);
+ }
+
+ return toolchain;
+ }
+ }
+
+ class VC15ToolchainProgram : VCToolchainProgram {
+ public override bool IsVersion (InstalledSDKInfo vcSDK)
+ {
+ return VisualStudioSDKHelper.GetInstance ().IsVisualStudio15 (vcSDK);
+ }
+
+ protected ToolchainProgram FindVCToolchainProgram (string tool, InstalledSDKInfo vcSDK)
+ {
+ if (toolchain == null) {
+ string toolPath = "";
+ if (!string.IsNullOrEmpty (vcSDK?.InstallationFolder)) {
+ string toolsVersionFilePath = Path.Combine (vcSDK.InstallationFolder, "Auxiliary", "Build", "Microsoft.VCToolsVersion.default.txt");
+ string toolsVersion = File.ReadAllLines (toolsVersionFilePath).ElementAt (0).Trim ();
+ string toolsVersionPath = Path.Combine (vcSDK.InstallationFolder, "Tools", "MSVC", toolsVersion);
+
+ if (Target64BitApplication ())
+ toolPath = Path.Combine (toolsVersionPath, "bin", "HostX64", "x64", tool);
+ else
+ toolPath = Path.Combine (toolsVersionPath, "bin", "HostX86", "x86", tool);
+ }
+
+ toolchain = new ToolchainProgram (tool, toolPath, vcSDK);
+ }
+
+ return toolchain;
+ }
+ }
+
+ class VC12Compiler : VC12ToolchainProgram {
+ public override ToolchainProgram FindVCToolchainProgram (InstalledSDKInfo vcSDK)
+ {
+ return FindVCToolchainProgram ("cl.exe", vcSDK);
+ }
+ }
+
+ class VC14Compiler : VC12Compiler {
+ public override bool IsVersion (InstalledSDKInfo vcSDK)
+ {
+ return VisualStudioSDKHelper.GetInstance ().IsVisualStudio14 (vcSDK);
+ }
+ }
+
+ class VC15Compiler : VC15ToolchainProgram {
+ public override ToolchainProgram FindVCToolchainProgram (InstalledSDKInfo vcSDK)
+ {
+ return FindVCToolchainProgram ("cl.exe", vcSDK);
+ }
+ }
+
+ class VC12Librarian : VC12ToolchainProgram {
+ public override ToolchainProgram FindVCToolchainProgram (InstalledSDKInfo vcSDK)
+ {
+ return FindVCToolchainProgram ("lib.exe", vcSDK);
+ }
+ }
+
+ class VC14Librarian : VC12Compiler {
+ public override bool IsVersion (InstalledSDKInfo vcSDK)
+ {
+ return VisualStudioSDKHelper.GetInstance ().IsVisualStudio14 (vcSDK);
+ }
+ }
+
+ class VC15Librarian : VC15ToolchainProgram {
+ public override ToolchainProgram FindVCToolchainProgram (InstalledSDKInfo vcSDK)
+ {
+ return FindVCToolchainProgram ("lib.exe", vcSDK);
+ }
+ }
+
+ class VC14Clang : VCToolchainProgram {
+ public override bool IsVersion (InstalledSDKInfo vcSDK)
+ {
+ return VisualStudioSDKHelper.GetInstance ().IsVisualStudio14 (vcSDK);
+ }
+
+ public override ToolchainProgram FindVCToolchainProgram (InstalledSDKInfo vcSDK)
+ {
+ if (toolchain == null) {
+ string clangPath = "";
+ if (!string.IsNullOrEmpty (vcSDK?.InstallationFolder)) {
+ clangPath = Path.Combine (new string [] { vcSDK.InstallationFolder, "ClangC2", "bin", Target64BitApplication () ? "amd64" : "x86", "clang.exe" });
+
+ if (!File.Exists (clangPath))
+ clangPath = "";
+ }
+
+ toolchain = new ToolchainProgram ("clang.exe", clangPath, vcSDK);
+ }
+
+ return toolchain;
+ }
+ }
+
+ class VC15Clang : VCToolchainProgram {
+ public override bool IsVersion (InstalledSDKInfo vcSDK)
+ {
+ return VisualStudioSDKHelper.GetInstance ().IsVisualStudio15 (vcSDK);
+ }
+
+ public override ToolchainProgram FindVCToolchainProgram (InstalledSDKInfo vcSDK)
+ {
+ if (toolchain == null) {
+ string clangPath = "";
+ if (!string.IsNullOrEmpty (vcSDK?.InstallationFolder)) {
+ string clangVersionFilePath = Path.Combine (vcSDK.InstallationFolder, "Auxiliary", "Build", "Microsoft.ClangC2Version.default.txt");
+ string clangVersion = File.ReadAllLines (clangVersionFilePath).ElementAt (0).Trim ();
+ string clangVersionPath = Path.Combine (vcSDK.InstallationFolder, "Tools", "ClangC2", clangVersion);
+
+ clangPath = Path.Combine (clangVersionPath, "bin", Target64BitApplication () ? "HostX64" : "HostX86", "clang.exe");
+ }
+
+ toolchain = new ToolchainProgram ("clang.exe", clangPath, vcSDK);
+ }
+
+ return toolchain;
+ }
+ }
+
+ class VisualStudioSDKToolchainHelper {
+ List<VCToolchainProgram> vcCompilers = new List<VCToolchainProgram> ();
+ List<VCToolchainProgram> vcLibrarians = new List<VCToolchainProgram> ();
+ List<VCToolchainProgram> vcClangCompilers = new List<VCToolchainProgram> ();
+
+ public VisualStudioSDKToolchainHelper ()
+ {
+ vcCompilers.Add (new VC12Compiler ());
+ vcCompilers.Add (new VC14Compiler ());
+ vcCompilers.Add (new VC15Compiler ());
+
+ vcLibrarians.Add (new VC12Librarian ());
+ vcLibrarians.Add (new VC14Librarian ());
+ vcLibrarians.Add (new VC15Librarian ());
+
+ vcClangCompilers.Add (new VC14Clang ());
+ vcClangCompilers.Add (new VC15Clang ());
+ }
+
+ static VisualStudioSDKToolchainHelper singletonInstance = new VisualStudioSDKToolchainHelper ();
+ static public VisualStudioSDKToolchainHelper GetInstance ()
+ {
+ return singletonInstance;
+ }
+
+ ToolchainProgram GetVCToolChainProgram (List<VCToolchainProgram> programs)
+ {
+ ToolchainProgram program = null;
+ var vcSDK = VisualStudioSDKHelper.GetInstance ().GetInstalledVisualStudioVCSDK ();
+ if (vcSDK?.ParentSDK != null) {
+ foreach (var item in programs) {
+ if (item.IsVersion (vcSDK.ParentSDK)) {
+ program = item.FindVCToolchainProgram (vcSDK);
+ break;
+ }
+ }
+ }
+
+ return program;
+ }
+
+ public ToolchainProgram GetVCCompiler ()
+ {
+ return GetVCToolChainProgram (vcCompilers);
+ }
+
+ public ToolchainProgram GetVCLibrarian ()
+ {
+ return GetVCToolChainProgram (vcLibrarians);
+ }
+
+ public ToolchainProgram GetVCClangCompiler ()
+ {
+ return GetVCToolChainProgram (vcClangCompilers);
+ }
+ }
+
+ static bool Target64BitApplication ()
+ {
+ // Should probably handled the --cross and sdk parameters.
+ return Environment.Is64BitProcess;
+ }
+
+ static string GetMonoDir ()
+ {
+ // Check that env doesn't already include needed values.
+ string monoInstallDir = GetEnv ("MONOPREFIX", "");
+ if (monoInstallDir.Length == 0) {
+ using (var baseKey = Microsoft.Win32.RegistryKey.OpenBaseKey (Microsoft.Win32.RegistryHive.LocalMachine,
+ Target64BitApplication () ? Microsoft.Win32.RegistryView.Registry64 : Microsoft.Win32.RegistryView.Registry32)) {
+
+ if (baseKey != null) {
+ using (var subKey = baseKey.OpenSubKey (@"SOFTWARE\Mono")) {
+ if (subKey != null)
+ monoInstallDir = (string)subKey.GetValue ("SdkInstallRoot", "");
+ }
+ }
+ }
+ }
+
+ return monoInstallDir;
+ }
+
+ static void AddMonoIncludePaths (List<string> includePaths)
+ {
+ includePaths.Add (Path.Combine (GetMonoDir (), @"include\mono-2.0"));
+ return;
+ }
+
+ static void AddMonoLibPaths (List<string> libPaths)
+ {
+ libPaths.Add (Path.Combine (GetMonoDir (), "lib"));
+ return;
+ }
+
+ static void AddIncludePaths (List<string> includePaths)
+ {
+ // Check that env doesn't already include needed values.
+ // If executed from a VS developer command prompt, all includes are already setup in env.
+ string includeEnv = GetEnv ("INCLUDE", "");
+ if (includeEnv.Length == 0) {
+ VisualStudioSDKHelper.GetInstance ().AddVisualStudioVCIncludePaths (includePaths);
+ WindowsSDKHelper.GetInstance ().AddCRuntimeSDKIncludePaths (includePaths);
+ WindowsSDKHelper.GetInstance ().AddWindowsSDKIncludePaths (includePaths);
+ }
+
+ AddMonoIncludePaths (includePaths);
+ includePaths.Add (".");
+
+ return;
+ }
+
+ static void AddLibPaths (List<string> libPaths)
+ {
+ // Check that env doesn't already include needed values.
+ // If executed from a VS developer command prompt, all libs are already setup in env.
+ string libEnv = GetEnv ("LIB", "");
+ if (libEnv.Length == 0) {
+ VisualStudioSDKHelper.GetInstance ().AddVisualStudioVCLibPaths (libPaths);
+ WindowsSDKHelper.GetInstance ().AddCRuntimeSDKLibPaths (libPaths);
+ WindowsSDKHelper.GetInstance ().AddWindowsSDKLibPaths (libPaths);
+ }
+
+ AddMonoLibPaths (libPaths);
+ libPaths.Add (".");
+
+ return;
+ }
+
+ static void AddVCSystemLibraries (ToolchainProgram program, bool staticLinkMono, bool staticLinkCRuntime, List<string> linkerArgs)
+ {
+ linkerArgs.Add ("kernel32.lib");
+ linkerArgs.Add ("version.lib");
+ linkerArgs.Add ("ws2_32.lib");
+ linkerArgs.Add ("mswsock.lib");
+ linkerArgs.Add ("psapi.lib");
+ linkerArgs.Add ("shell32.lib");
+ linkerArgs.Add ("oleaut32.lib");
+ linkerArgs.Add ("ole32.lib");
+ linkerArgs.Add ("winmm.lib");
+ linkerArgs.Add ("user32.lib");
+ linkerArgs.Add ("advapi32.lib");
+
+ if (program != null && program.ParentSDK != null && VisualStudioSDKHelper.GetInstance ().IsVisualStudio12 (program.ParentSDK)) {
+ if (staticLinkCRuntime) {
+ // Static release c-runtime support.
+ linkerArgs.Add ("libcmt.lib");
+ linkerArgs.Add ("oldnames.lib");
+ } else {
+ // Dynamic release c-runtime support.
+ linkerArgs.Add ("msvcrt.lib");
+ linkerArgs.Add ("oldnames.lib");
+ }
+ } else {
+ if (staticLinkCRuntime) {
+ // Static release c-runtime support.
+ linkerArgs.Add ("libucrt.lib");
+ linkerArgs.Add ("libvcruntime.lib");
+ linkerArgs.Add ("libcmt.lib");
+ linkerArgs.Add ("oldnames.lib");
+ } else {
+ // Dynamic release c-runtime support.
+ linkerArgs.Add ("ucrt.lib");
+ linkerArgs.Add ("vcruntime.lib");
+ linkerArgs.Add ("msvcrt.lib");
+ linkerArgs.Add ("oldnames.lib");
+ }
+ }
+
+ return;
+ }
+
+ static void AddGCCSystemLibraries (ToolchainProgram program, bool staticLinkMono, bool staticLinkCRuntime, List<string> linkerArgs)
+ {
+ if (MakeBundle.compress)
+ linkerArgs.Add ("-lz");
+
+ return;
+ }
+
+ static void AddSystemLibraries (ToolchainProgram program, bool staticLinkMono, bool staticLinkCRuntime, List<string> linkerArgs)
+ {
+ if (program.IsVSToolChain)
+ AddVCSystemLibraries (program, staticLinkMono, staticLinkCRuntime, linkerArgs);
+ else
+ AddGCCSystemLibraries (program, staticLinkMono, staticLinkCRuntime, linkerArgs);
+
+ return;
+ }
+
+ static void AddMonoLibraries (ToolchainProgram program, bool staticLinkMono, bool staticLinkCRuntime, List<string> linkerArguments)
+ {
+ bool vsToolChain = program.IsVSToolChain;
+ string libPrefix = !vsToolChain ? "-l" : "";
+ string libExtension = vsToolChain ? ".lib" : "";
+ string monoLibrary = GetEnv ("LIBMONO", "");
+
+ if (monoLibrary.Length == 0) {
+ if (staticLinkMono) {
+ if (program.IsGCCToolChain) {
+ Console.WriteLine ( @"Warning: Static linking using default Visual Studio build libmono-static-sgen" +
+ @"might cause link errors when using GCC toolchain.");
+ }
+ monoLibrary = "libmono-static-sgen";
+ } else {
+ monoLibrary = "mono-2.0-sgen";
+ }
+ }
+
+ if (!Path.IsPathRooted (monoLibrary)) {
+ if (!monoLibrary.EndsWith (libExtension))
+ monoLibrary = monoLibrary + libExtension;
+
+ linkerArguments.Add (libPrefix + monoLibrary);
+ } else {
+ linkerArguments.Add (monoLibrary);
+ }
+
+ return;
+ }
+
+ static void AddVCCompilerArguments (ToolchainProgram program, bool staticLinkMono, bool staticLinkCRuntime, List<string> compilerArgs)
+ {
+ List<string> includePaths = new List<string> ();
+ AddIncludePaths (includePaths);
+
+ if (staticLinkCRuntime)
+ // Add targeted c-runtime (MT = static release).
+ compilerArgs.Add ("/MT");
+ else
+ // Add targeted c-runtime (MD = dynamic release).
+ compilerArgs.Add ("/MD");
+
+ // Add include search paths.
+ foreach (string include in includePaths)
+ compilerArgs.Add (String.Format("/I {0}", program.QuoteArg (include)));
+
+ return;
+ }
+
+ static void AddGCCCompilerArguments (ToolchainProgram program, bool staticLinkMono, bool staticLinkCRuntime, List<string> compilerArgs)
+ {
+ List<string> includePaths = new List<string> ();
+ AddMonoIncludePaths (includePaths);
+
+ // Add include search paths.
+ foreach (string include in includePaths)
+ compilerArgs.Add (String.Format ("-I {0}", program.QuoteArg (include)));
+
+ return;
+ }
+
+ static void AddCompilerArguments (ToolchainProgram program, bool staticLinkMono, bool staticLinkCRuntime, List<string> compilerArgs)
+ {
+ if (program.IsVSToolChain)
+ AddVCCompilerArguments (program, staticLinkMono, staticLinkCRuntime, compilerArgs);
+ else
+ AddGCCCompilerArguments (program, staticLinkMono, staticLinkCRuntime, compilerArgs);
+
+ return;
+ }
+
+ static void AddVCLinkerArguments (ToolchainProgram linker, bool staticLinkMono, bool staticLinkCRuntime, string customMain, string outputFile, List<string> linkerArgs)
+ {
+ linkerArgs.Add ("/link");
+
+ var subsystem = GetEnv ("VCSUBSYSTEM", "windows");
+ linkerArgs.Add ("/SUBSYSTEM:" + subsystem);
+
+ if (customMain != null && customMain.Length != 0)
+ linkerArgs.Add (linker.QuoteArg (customMain));
+ else
+ linkerArgs.Add ("/ENTRY:mainCRTStartup");
+
+ // Ignore other c-runtime directives from linked libraries.
+ linkerArgs.Add ("/NODEFAULTLIB");
+
+ AddMonoLibraries (linker, staticLinkMono, staticLinkCRuntime, linkerArgs);
+ AddSystemLibraries (linker, staticLinkMono, staticLinkCRuntime, linkerArgs);
+
+ // Add library search paths.
+ List<string> libPaths = new List<string> ();
+ AddLibPaths (libPaths);
+
+ foreach (string lib in libPaths)
+ linkerArgs.Add (String.Format ("/LIBPATH:{0}", linker.QuoteArg (lib)));
+
+ // Linker output target.
+ linkerArgs.Add ("/OUT:" + linker.QuoteArg (outputFile));
+
+ return;
+ }
+
+ static void AddGCCLinkerArguments (ToolchainProgram linker, bool staticLinkMono, bool staticLinkCRuntime, string customMain, string outputFile, List<string> linkerArgs)
+ {
+ // Add library search paths.
+ List<string> libPaths = new List<string> ();
+ AddMonoLibPaths (libPaths);
+
+ foreach (string lib in libPaths)
+ linkerArgs.Add (String.Format ("-L {0}", linker.QuoteArg (lib)));
+
+ // Add libraries.
+ if (staticLinkMono)
+ linkerArgs.Add ("-Wl,-Bstatic");
+
+ AddMonoLibraries (linker, staticLinkMono, staticLinkCRuntime, linkerArgs);
+
+ if (staticLinkMono)
+ linkerArgs.Add ("-Wl,-Bdynamic");
+
+ AddSystemLibraries (linker, staticLinkMono, staticLinkCRuntime, linkerArgs);
+
+ // Linker output target.
+ linkerArgs.Add ("-o " + linker.QuoteArg (outputFile));
+ }
+
+ static void AddLinkerArguments (ToolchainProgram program, bool staticLinkMono, bool staticLinkCRuntime, string customMain, string outputFile, List<string> linkerArgs)
+ {
+ if (program.IsVSToolChain)
+ AddVCLinkerArguments (program, staticLinkMono, staticLinkCRuntime, customMain, outputFile, linkerArgs);
+ else
+ AddGCCLinkerArguments (program, staticLinkMono, staticLinkCRuntime, customMain, outputFile, linkerArgs);
+
+ return;
+ }
+
+ static void AddVCLibrarianCompilerArguments (ToolchainProgram compiler, string sourceFile, bool staticLinkMono, bool staticLinkCRuntime, List<string> compilerArgs, out string objectFile)
+ {
+ compilerArgs.Add ("/c");
+ compilerArgs.Add (compiler.QuoteArg (sourceFile));
+
+ objectFile = sourceFile + ".obj";
+ compilerArgs.Add (String.Format ("/Fo" + compiler.QuoteArg (objectFile)));
+
+ return;
+ }
+
+ static void AddGCCLibrarianCompilerArguments (ToolchainProgram compiler, string sourceFile, bool staticLinkMono, bool staticLinkCRuntime, List<string> compilerArgs, out string objectFile)
+ {
+ compilerArgs.Add ("-c");
+ compilerArgs.Add (compiler.QuoteArg (sourceFile));
+
+ objectFile = sourceFile + ".o";
+ compilerArgs.Add (String.Format ("-o " + compiler.QuoteArg (objectFile)));
+
+ return;
+ }
+
+ static void AddVCLibrarianLinkerArguments (ToolchainProgram librarian, string [] objectFiles, bool staticLinkMono, bool staticLinkCRuntime, string outputFile, List<string> librarianArgs)
+ {
+ foreach (var objectFile in objectFiles)
+ librarianArgs.Add (librarian.QuoteArg (objectFile));
+
+ // Add library search paths.
+ List<string> libPaths = new List<string> ();
+ AddLibPaths (libPaths);
+
+ foreach (string lib in libPaths) {
+ librarianArgs.Add (String.Format ("/LIBPATH:{0}", librarian.QuoteArg (lib)));
+ }
+
+ AddMonoLibraries (librarian, staticLinkMono, staticLinkCRuntime, librarianArgs);
+
+ librarianArgs.Add ("/OUT:" + librarian.QuoteArg (output));
+
+ return;
+ }
+
+ static void AddGCCLibrarianLinkerArguments (ToolchainProgram librarian, string [] objectFiles, bool staticLinkMono, bool staticLinkCRuntime, string outputFile, List<string> librarianArgs)
+ {
+ foreach (var objectFile in objectFiles)
+ librarianArgs.Add (librarian.QuoteArg (objectFile));
+
+ // Add library search paths.
+ List<string> libPaths = new List<string> ();
+ AddMonoLibPaths (libPaths);
+
+ foreach (string lib in libPaths)
+ librarianArgs.Add (String.Format ("-L {0}", librarian.QuoteArg (lib)));
+
+ AddMonoLibraries (librarian, staticLinkMono, staticLinkCRuntime, librarianArgs);
+
+ librarianArgs.Add ("-o " + librarian.QuoteArg (output));
+
+ return;
+ }
+
+ static ToolchainProgram GetAssemblerCompiler ()
+ {
+ // First check if env is set (old behavior) and use that.
+ string assembler = GetEnv ("AS", "");
+ if (assembler.Length != 0)
+ return new ToolchainProgram ("AS", assembler);
+
+ var vcClangAssembler = VisualStudioSDKToolchainHelper.GetInstance ().GetVCClangCompiler ();
+ if (vcClangAssembler == null)
+ // Fallback to GNU assembler if clang for VS was not installed.
+ // Why? because mkbundle generates GNU assembler not compilable by VS tools like ml.
+ return new ToolchainProgram ("AS", "as.exe");
+
+ return vcClangAssembler;
+ }
+
+ static ToolchainProgram GetCCompiler ()
+ {
+ // First check if env is set (old behavior) and use that.
+ string compiler = GetEnv ("CC", "");
+ if (compiler.Length != 0)
+ return new ToolchainProgram ("CC", compiler);
+
+ var vcCompiler = VisualStudioSDKToolchainHelper.GetInstance ().GetVCCompiler ();
+ if (vcCompiler == null)
+ // Fallback to cl.exe if VC compiler was not installed.
+ return new ToolchainProgram ("cl.exe", "cl.exe");
+
+ return vcCompiler;
+ }
+
+ static ToolchainProgram GetLibrarian ()
+ {
+ ToolchainProgram vcLibrarian = VisualStudioSDKToolchainHelper.GetInstance ().GetVCLibrarian ();
+ if (vcLibrarian == null)
+ // Fallback to lib.exe if VS was not installed.
+ return new ToolchainProgram ("lib.exe", "lib.exe");
+
+ return vcLibrarian;
+ }
+
+ static string GetCompileAndLinkCommand (ToolchainProgram compiler, string sourceFile, string objectFile, string customMain, bool staticLinkMono, bool staticLinkCRuntime, string outputFile)
+ {
+ var compilerArgs = new List<string> ();
+
+ AddCompilerArguments (compiler, staticLinkMono, staticLinkCRuntime, compilerArgs);
+
+ // Add source file to compile.
+ compilerArgs.Add (compiler.QuoteArg (sourceFile));
+
+ // Add assembled object file.
+ compilerArgs.Add (compiler.QuoteArg (objectFile));
+
+ // Add linker arguments.
+ AddLinkerArguments (compiler, staticLinkMono, staticLinkCRuntime, customMain, outputFile, compilerArgs);
+
+ return String.Format ("{0} {1}", compiler.QuoteArg (compiler.Path), String.Join (" ", compilerArgs.ToArray ()));
+ }
+
+ static string GetLibrarianCompilerCommand (ToolchainProgram compiler, string sourceFile, bool staticLinkMono, bool staticLinkCRuntime, out string objectFile)
+ {
+ var compilerArgs = new List<string> ();
+
+ AddCompilerArguments (compiler, staticLinkMono, staticLinkCRuntime, compilerArgs);
+
+ if (compiler.IsVSToolChain)
+ AddVCLibrarianCompilerArguments (compiler, sourceFile, staticLinkMono, staticLinkCRuntime, compilerArgs, out objectFile);
+ else
+ AddGCCLibrarianCompilerArguments (compiler, sourceFile, staticLinkMono, staticLinkCRuntime, compilerArgs, out objectFile);
+
+ return String.Format ("{0} {1}", compiler.QuoteArg (compiler.Path), String.Join (" ", compilerArgs.ToArray ()));
+ }
+
+ static string GetLibrarianLinkerCommand (ToolchainProgram librarian, string [] objectFiles, bool staticLinkMono, bool staticLinkCRuntime, string outputFile)
+ {
+ var librarianArgs = new List<string> ();
+
+ if (librarian.IsVSToolChain)
+ AddVCLibrarianLinkerArguments (librarian, objectFiles, staticLinkMono, staticLinkCRuntime, outputFile, librarianArgs);
+ else
+ AddGCCLibrarianLinkerArguments (librarian, objectFiles, staticLinkMono, staticLinkCRuntime, outputFile, librarianArgs);
+
+ return String.Format ("{0} {1}", librarian.QuoteArg (librarian.Path), String.Join (" ", librarianArgs.ToArray ()));
+ }
+#endregion