diff --git a/.gitignore b/.gitignore index fc86a341..162ebdbf 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,6 @@ autom4te.cache missing *Makefile *Makefile.in -*.dll *.exe bin/ *.userprefs diff --git a/deps/vs2017/Microsoft.VisualStudio.Setup.Configuration.Interop.dll b/deps/vs2017/Microsoft.VisualStudio.Setup.Configuration.Interop.dll new file mode 100644 index 00000000..9c0fc33b Binary files /dev/null and b/deps/vs2017/Microsoft.VisualStudio.Setup.Configuration.Interop.dll differ diff --git a/deps/vs2017/Microsoft.VisualStudio.Setup.Configuration.Interop.xml b/deps/vs2017/Microsoft.VisualStudio.Setup.Configuration.Interop.xml new file mode 100644 index 00000000..5d922347 --- /dev/null +++ b/deps/vs2017/Microsoft.VisualStudio.Setup.Configuration.Interop.xml @@ -0,0 +1,485 @@ + + + + Microsoft.VisualStudio.Setup.Configuration.Interop + + + + + A enumerator of installed objects. + + + + + Retrieves the next set of product instances in the enumeration sequence. + + The number of product instances to retrieve. + A pointer to an array of . + A pointer to the number of product instances retrieved. If celt is 1 this parameter may be NULL. + + + + Skips the next set of product instances in the enumeration sequence. + + The number of product instances to skip. + + + + Resets the enumeration sequence to the beginning. + + + + + Creates a new enumeration object in the same state as the current enumeration object: the new object points to the same place in the enumeration sequence. + + A pointer to a pointer to a new interface. If the method fails, this parameter is undefined. + + + + The state of an . + + + + + The instance state has not been determined. + + + + + The instance installation path exists. + + + + + A product is registered to the instance. + + + + + No reboot is required for the instance. + + + + + No errors were reported for the instance. + + + + + The instance represents a complete install. + + + + + Gets information about product instances set up on the machine. + + + + + Enumerates all completed product instances installed. + + An enumeration of installed product instances. + + + + Gets the instance for the current process path. + + The instance for the current process path. + + + + Gets the instance for the given path. + + Path used to determine instance + The instance for the given path. + + + + Enumerates all product instances. + + An enumeration of all product instances. + + + + Gets information about product instances set up on the machine. + + + + + Enumerates all product instances installed. + + An enumeration of installed product instances. + + + + Gets the instance for the current process path. + + The instance for the current process path. + + + + Gets the instance for the given path. + + Path used to determine instance + The instance for the given path. + + + + Information about the error state of the instance. + + + + + Gets an array of failed package references. + + An array of failed package references. + + + + Gets an array of skipped package references. + + An array of skipped package references. + + + + A reference to a failed package. + + + You can enumerate all properties of basic types by casting to an . + + + + + Gets the general package identifier. + + The general package identifier. + + + + Gets the version of the package. + + The version of the package. + + + + Gets the target process architecture of the package. + + The target process architecture of the package. + + + + Gets the language and optional region identifier. + + The language and optional region identifier. + + + + Gets the build branch of the package. + + The build branch of the package. + + + + Gets the type of the package. + + The type of the package. + + + + Gets the unique identifier consisting of all defined tokens. + + The unique identifier consisting of all defined tokens. + + + + Gets a value indicating whether the package refers to an external extension. + + A value indicating whether the package refers to an external extension. + + + + Helper functions. + + + + + Parses a dotted quad version string into a 64-bit unsigned integer. + + The dotted quad version string to parse, e.g. 1.2.3.4. + A 64-bit unsigned integer representing the version. You can compare this to other versions. + + + + Parses a dotted quad version string into a 64-bit unsigned integer. + + The string containing 1 or 2 dotted quad version strings to parse, e.g. [1.0,) that means 1.0.0.0 or newer. + A 64-bit unsigned integer representing the minimum version, which may be 0. You can compare this to other versions. + A 64-bit unsigned integer representing the maximum version, which may be MAXULONGLONG. You can compare this to other versions. + + + + Information about an instance of a product. + + + You can enumerate all properties of basic types by casting to an . + + + + + Gets the instance identifier (should match the name of the parent instance directory). + + The instance identifier. + + + + Gets the local date and time when the installation was originally installed. + + The local date and time when the installation was originally installed. + + + + Gets the unique name of the installation, often indicating the branch and other information used for telemetry. + + The unique name of the installation, often indicating the branch and other information used for telemetry. + + + + Gets the path to the installation root of the product. + + The path to the installation root of the product. + + + + Gets the version of the product installed in this instance. + + The version of the product installed in this instance. + + + + Gets the display name (title) of the product installed in this instance. + + The LCID for the display name. + The display name (title) of the product installed in this instance. + + + + Gets the description of the product installed in this instance. + + The LCID for the description. + The description of the product installed in this instance. + + + + Resolves the optional relative path to the root path of the instance. + + A relative path within the instance to resolve, or NULL to get the root path. + The full path to the optional relative path within the instance. If the relative path is NULL, the root path will always terminate in a backslash. + + + + Gets the state of the instance. + + The state of the instance. + + + + Gets an array of package references registered to the instance. + + An array of package references registered to the instance. + + + + Gets a package reference to the product registered to the instance + + A package reference to the product registered to the instance. This may be null if does not return . + + + + Gets the relative path to the product application, if available. + + The relative path to the product application, if available. + + + + Gets the error state of the instance, if available. + + The error state of the instance, if available. + + + + Gets a value indicating whether the instance can be launched. + + Whether the instance can be launched. + + An instance could have had errors during install but still be launched. Some features may not work correctly, but others will. + + + + + Gets a value indicating whether the instance is complete. + + Whether the instance is complete. + + An instance is complete if it had no errors during install, resume, or repair. + + + + + Gets product-specific properties. + + An of product-specific properties, or null if no properties are defined. + + + + Gets the directory path to the setup engine that installed the instance. + + The directory path to the setup engine that installed the instance. + + + + Information about an instance of a product. + + + You can enumerate all properties of basic types by casting to an . + + + + + Gets the instance identifier (should match the name of the parent instance directory). + + The instance identifier. + + + + Gets the local date and time when the installation was originally installed. + + The local date and time when the installation was originally installed. + + + + Gets the unique name of the installation, often indicating the branch and other information used for telemetry. + + The unique name of the installation, often indicating the branch and other information used for telemetry. + + + + Gets the path to the installation root of the product. + + The path to the installation root of the product. + + + + Gets the version of the product installed in this instance. + + The version of the product installed in this instance. + + + + Gets the display name (title) of the product installed in this instance. + + The LCID for the display name. + The display name (title) of the product installed in this instance. + + + + Gets the description of the product installed in this instance. + + The LCID for the description. + The description of the product installed in this instance. + + + + Resolves the optional relative path to the root path of the instance. + + A relative path within the instance to resolve, or NULL to get the root path. + The full path to the optional relative path within the instance. If the relative path is NULL, the root path will always terminate in a backslash. + + + + A reference to a package. + + + You can enumerate all properties of basic types by casting to an . + + + + + Gets the general package identifier. + + The general package identifier. + + + + Gets the version of the package. + + The version of the package. + + + + Gets the target process architecture of the package. + + The target process architecture of the package. + + + + Gets the language and optional region identifier. + + The language and optional region identifier. + + + + Gets the build branch of the package. + + The build branch of the package. + + + + Gets the type of the package. + + The type of the package. + + + + Gets the unique identifier consisting of all defined tokens. + + The unique identifier consisting of all defined tokens. + + + + Gets a value indicating whether the package refers to an external extension. + + A value indicating whether the package refers to an external extension. + + + + Provides named properties. + + + You can get this from an , , or derivative. + + + + + Gets an array of property names in this property store. + + An array of property names in this property store. + + + + Gets the value of a named property in this property store. + + The name of the property to get. + The value of the property. + + + + The implementation of . + + + + + Class that implements . + + + + diff --git a/src/Core/Toolchains/MSVCToolchain.cs b/src/Core/Toolchains/MSVCToolchain.cs index 35ad456d..fe59dae6 100644 --- a/src/Core/Toolchains/MSVCToolchain.cs +++ b/src/Core/Toolchains/MSVCToolchain.cs @@ -5,28 +5,31 @@ using System.IO; using System.Linq; using System.Text.RegularExpressions; using Microsoft.Win32; +using Microsoft.VisualStudio.Setup.Configuration; +using System.Runtime.InteropServices; namespace CppSharp { - /// Represents a Visual Studio version. + /// Represents a Visual Studio version. public enum VisualStudioVersion { VS2012 = 11, VS2013 = 12, VS2015 = 14, + VS2017 = 15, Latest, } - /// Represents a toolchain with associated version and directory. + /// Represents a toolchain with associated version and directory. public struct ToolchainVersion { - /// Version of the toolchain. + /// Version of the toolchain. public float Version; - /// Directory location of the toolchain. + /// Directory location of the toolchain. public string Directory; - /// Extra data value associated with the toolchain. + /// Extra data value associated with the toolchain. public string Value; public override string ToString() @@ -35,6 +38,17 @@ namespace CppSharp } } + /// + /// Describes the major and minor version of something. + /// Each version must be at least non negative and smaller than 100 + /// + public struct Version + { + public int Major; + + public int Minor; + } + public static class MSVCToolchain { static void DumpSdks(string sku, IEnumerable sdks) @@ -44,7 +58,7 @@ namespace CppSharp Console.WriteLine("\t({0}) {1}", sdk.Version, sdk.Directory); } - /// Dumps the detected SDK versions. + /// Dumps the detected SDK versions. public static void DumpSdks() { List vsSdks; @@ -68,7 +82,7 @@ namespace CppSharp DumpSdks("MSBuild", msbuildSdks); } - /// Dumps include directories for selected toolchain. + /// Dumps include directories for selected toolchain. public static void DumpSdkIncludes(VisualStudioVersion vsVersion = VisualStudioVersion.Latest) { @@ -78,20 +92,23 @@ namespace CppSharp Console.WriteLine("\t{0}", include); } - public static int GetCLVersion(VisualStudioVersion vsVersion) + public static Version GetCLVersion(VisualStudioVersion vsVersion) { - int clVersion; + Version clVersion; switch (vsVersion) { case VisualStudioVersion.VS2012: - clVersion = 17; + clVersion = new Version { Major = 17, Minor = 0}; break; case VisualStudioVersion.VS2013: - clVersion = 18; + clVersion = new Version { Major = 18, Minor = 0 }; break; case VisualStudioVersion.VS2015: + clVersion = new Version { Major = 19, Minor = 0 }; + break; + case VisualStudioVersion.VS2017: case VisualStudioVersion.Latest: - clVersion = 19; + clVersion = new Version { Major = 19, Minor = 10 }; break; default: throw new Exception("Unknown Visual Studio version"); @@ -109,8 +126,10 @@ namespace CppSharp case VisualStudioVersion.VS2013: return 12; case VisualStudioVersion.VS2015: - case VisualStudioVersion.Latest: return 14; + case VisualStudioVersion.VS2017: + case VisualStudioVersion.Latest: + return 15; default: throw new Exception("Unknown Visual Studio version"); } @@ -163,30 +182,30 @@ namespace CppSharp var windowsKitSdk = (!string.IsNullOrWhiteSpace(kitsRootKey)) ? windowsKitsSdks.Find(version => version.Value == kitsRootKey) : windowsKitsSdks.Last(); - // If for some reason we cannot find the SDK version reported by VS // in the system, then fallback to the latest version found. if (windowsKitSdk.Value == null) - windowsKitSdk = windowsKitsSdks.Last(); - + windowsKitSdk = windowsKitsSdks.Last(); return windowsKitSdk; } - /// Gets the system include folders for the given Visual Studio version. public static List GetSystemIncludes(VisualStudioVersion vsVersion) { var vsSdk = GetVSToolchain(vsVersion); - int windowsSdkMajorVer; - var windowsKitSdk = GetWindowsKitsToolchain(vsVersion, out windowsSdkMajorVer); - var vsDir = vsSdk.Directory; vsDir = vsDir.Substring(0, vsDir.LastIndexOf(@"\Common7\IDE", StringComparison.Ordinal)); var includes = new List(); + if(vsVersion == VisualStudioVersion.VS2017 || + vsVersion == VisualStudioVersion.Latest) + return GetSystemIncludesVS2017(vsDir); includes.Add(Path.Combine(vsDir, @"VC\include")); + int windowsSdkMajorVer; + var windowsKitSdk = GetWindowsKitsToolchain(vsVersion, out windowsSdkMajorVer); + List windowsSdks; GetWindowsSdks(out windowsSdks); @@ -283,7 +302,11 @@ namespace CppSharp return includes; } + /// /// Gets .NET framework installation directories. + /// + /// Collection holding information about available .Net-framework-sdks + /// Success of the operation public static bool GetNetFrameworkSdks(out List versions) { versions = new List(); @@ -304,7 +327,11 @@ namespace CppSharp return versions.Count != 0; } + /// /// Gets MSBuild installation directories. + /// + /// Collection holding information about available ms-build-sdks + /// Success of the operation public static bool GetMSBuildSdks(out List versions) { versions = new List(); @@ -325,7 +352,11 @@ namespace CppSharp return versions.Count != 0; } + /// /// Gets Windows SDK installation directories. + /// + /// Collection holding information about available windows-sdks + /// Success of the operation public static bool GetWindowsSdks(out List versions) { versions = new List(); @@ -339,14 +370,16 @@ namespace CppSharp GetToolchainsFromSystemRegistry( "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows", "InstallationFolder", versions, RegistryView.Registry64); - } - + } versions.Sort((v1, v2) => (int)(v1.Version - v2.Version)); - return versions.Count != 0; } + /// /// Gets Windows Kits SDK installation directories. + /// + /// Collection holding information about available WindowsKitsSdks + /// Success of the operation public static bool GetWindowsKitsSdks(out List versions) { versions = new List(); @@ -367,7 +400,11 @@ namespace CppSharp return true; } + /// /// Gets Visual Studio installation directories. + /// + /// Collection holding information about available Visual Studio instances + /// Success of the operation public static bool GetVisualStudioSdks(out List versions) { versions = new List(); @@ -394,8 +431,10 @@ namespace CppSharp "InstallDir", versions, RegistryView.Registry64); } - versions.Sort((v1, v2) => (int)(v1.Version - v2.Version)); + //Check for VS 2017 + GetVs2017Instances(versions); + versions.Sort((v1, v2) => (int)(v1.Version - v2.Version)); return true; } @@ -539,5 +578,147 @@ namespace CppSharp return hive; } + +#region VS2017 + + /// + /// Returns all system includes of the installed VS 2017 instance. + /// + /// Path to the visual studio installation (for identifying the correct instance) + /// The system includes + private static List GetSystemIncludesVS2017(string vsDir) + { + List includes = new List(); + //They includes are in a different folder + const int REGDB_E_CLASSNOTREG = unchecked((int)0x80040154); + try + { + var query = new SetupConfiguration(); + var query2 = (ISetupConfiguration2)query; + var e = query2.EnumAllInstances(); + + var helper = (ISetupHelper)query; + + int fetched; + var instances = new ISetupInstance[1]; + do + { + e.Next(1, instances, out fetched); + if (fetched > 0) + { + var instance = (ISetupInstance2)instances[0]; + if (instance.GetInstallationPath() != vsDir) continue; + var packages = instance.GetPackages(); + var vc_tools = from package in packages + where package.GetId().Contains("Microsoft.VisualStudio.Component.VC.Tools") + orderby package.GetId() + select package; + if (vc_tools.Count() > 0) + { // Tools found, get path + var path = instance.GetInstallationPath(); + var versionFilePath = path + @"\VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt"; + var version = System.IO.File.ReadLines(versionFilePath).ElementAt(0).Trim(); + includes.Add(path + @"\VC\Tools\MSVC\" + version + @"\include"); + includes.Add(path + @"\VC\Tools\MSVC\" + version + @"\atlmfc\include"); + } + var sdks = from package in packages + where package.GetId().Contains("Windows10SDK") || package.GetId().Contains("Windows81SDK") || package.GetId().Contains("Win10SDK_10") + select package; + var win10sdks = from sdk in sdks + where sdk.GetId().Contains("Windows10SDK") + select sdk; + var win8sdks = from sdk in sdks + where sdk.GetId().Contains("Windows81SDK") + select sdk; + if (win10sdks.Count() > 0) + { + var sdk = win10sdks.Last(); + var path = @"C:\Program Files (x86)\Windows Kits\10\include\" + "10.0." + sdk.GetId().Substring(46) + ".0"; //Microsoft.VisualStudio.Component.Windows10SDK. = 46 chars + var shared = Path.Combine(path, "shared"); + var um = Path.Combine(path, "um"); + var winrt = Path.Combine(path, "winrt"); + var ucrt = Path.Combine(path, "ucrt"); + Console.WriteLine(path); + if (Directory.Exists(shared) && + Directory.Exists(um) && + Directory.Exists(winrt) && + Directory.Exists(ucrt)) + { + includes.Add(shared); + includes.Add(um); + includes.Add(winrt); + includes.Add(ucrt); + } + } + else if (win8sdks.Count() > 0) + { + includes.Add(@"C:\Program Files (x86)\Windows Kits\8.1\include\shared"); + includes.Add(@"C:\Program Files (x86)\Windows Kits\8.1\include\um"); + includes.Add(@"C:\Program Files (x86)\Windows Kits\8.1\include\winrt"); + } + + return includes; //We've collected all information. + } + + } + while (fetched > 0); + } + catch (COMException ex) when (ex.HResult == REGDB_E_CLASSNOTREG) + { + Console.WriteLine("The query API is not registered. Assuming no instances are installed."); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Error 0x{ex.HResult:x8}: {ex.Message}"); + } + return includes; + } + + /// + /// Tries to get all vs 2017 instances. + /// + /// Collection holding available visual studio instances + /// Success of the operation + private static bool GetVs2017Instances(ICollection versions) + { + const int REGDB_E_CLASSNOTREG = unchecked((int)0x80040154); + try + { + var query = new SetupConfiguration(); + var query2 = (ISetupConfiguration2)query; + var e = query2.EnumAllInstances(); + int fetched; + var instances = new ISetupInstance[1]; + do + { + e.Next(1, instances, out fetched); + if (fetched > 0) + { + var instance = (ISetupInstance2)instances[0]; + var packages = instance.GetPackages(); + var toolchain = new ToolchainVersion + { + Directory = instance.GetInstallationPath() + @"\Common7\IDE", + Version = Single.Parse(instance.GetInstallationVersion().Remove(2)), + Value = null // Not used currently + }; + versions.Add(toolchain); + } + } + while (fetched > 0); + } + catch (COMException ex) when (ex.HResult == REGDB_E_CLASSNOTREG) + { + Console.WriteLine("The query API is not registered. Assuming no instances are installed."); + return false; + } + catch (Exception ex) + { + Console.Error.WriteLine($"Error 0x{ex.HResult:x8}: {ex.Message}"); + return false; + } + return true; + } +#endregion } } diff --git a/src/Core/premake5.lua b/src/Core/premake5.lua index 8e38a678..78c6899e 100644 --- a/src/Core/premake5.lua +++ b/src/Core/premake5.lua @@ -8,9 +8,12 @@ project "CppSharp" files { "**.cs" } vpaths { ["*"] = "*" } - + + libdirs{ depsdir .."/vs2017" } + links { "System", "System.Core", + "Microsoft.VisualStudio.Setup.Configuration.Interop" } diff --git a/src/Parser/ParserOptions.cs b/src/Parser/ParserOptions.cs index 04c774e9..bb331db7 100644 --- a/src/Parser/ParserOptions.cs +++ b/src/Parser/ParserOptions.cs @@ -20,7 +20,8 @@ namespace CppSharp.Parser NoBuiltinIncludes = true; NoStandardIncludes = true; Abi = CppAbi.Microsoft; - ToolSetToUse = MSVCToolchain.GetCLVersion(vsVersion) * 10000000; + var clVersion = MSVCToolchain.GetCLVersion(vsVersion); + ToolSetToUse = clVersion.Major * 10000000 + clVersion.Minor * 100000; AddArguments("-fms-extensions"); AddArguments("-fms-compatibility");