-
Notifications
You must be signed in to change notification settings - Fork 29.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
win,build: add Visual Studio 2017 support #11867
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -59,6 +59,7 @@ ipch/ | |
*.VC.opendb | ||
.vs/ | ||
.vscode/ | ||
/Set_VS*.bat | ||
|
||
/config.mk | ||
/config.gypi | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,270 @@ | ||
// Copyright 2017 - Refael Ackermann | ||
// Distributed under MIT style license | ||
// See accompanying file LICENSE at https://github.com/node4good/windows-autoconf | ||
|
||
// Usage: | ||
// powershell -ExecutionPolicy Unrestricted -Version "2.0" -Command "&{Add-Type -Path Find-VS2017.cs; [VisualStudioConfiguration.Main]::Query()}" | ||
using System; | ||
using System.Text; | ||
using System.Runtime.InteropServices; | ||
|
||
namespace VisualStudioConfiguration | ||
{ | ||
[Flags] | ||
public enum InstanceState : uint | ||
{ | ||
None = 0, | ||
Local = 1, | ||
Registered = 2, | ||
NoRebootRequired = 4, | ||
NoErrors = 8, | ||
Complete = 4294967295, | ||
} | ||
|
||
[Guid("6380BCFF-41D3-4B2E-8B2E-BF8A6810C848")] | ||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] | ||
[ComImport] | ||
public interface IEnumSetupInstances | ||
{ | ||
|
||
void Next([MarshalAs(UnmanagedType.U4), In] int celt, | ||
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Interface), Out] ISetupInstance[] rgelt, | ||
[MarshalAs(UnmanagedType.U4)] out int pceltFetched); | ||
|
||
void Skip([MarshalAs(UnmanagedType.U4), In] int celt); | ||
|
||
void Reset(); | ||
|
||
[return: MarshalAs(UnmanagedType.Interface)] | ||
IEnumSetupInstances Clone(); | ||
} | ||
|
||
[Guid("42843719-DB4C-46C2-8E7C-64F1816EFD5B")] | ||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] | ||
[ComImport] | ||
public interface ISetupConfiguration | ||
{ | ||
} | ||
|
||
[Guid("26AAB78C-4A60-49D6-AF3B-3C35BC93365D")] | ||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] | ||
[ComImport] | ||
public interface ISetupConfiguration2 : ISetupConfiguration | ||
{ | ||
|
||
[return: MarshalAs(UnmanagedType.Interface)] | ||
IEnumSetupInstances EnumInstances(); | ||
|
||
[return: MarshalAs(UnmanagedType.Interface)] | ||
ISetupInstance GetInstanceForCurrentProcess(); | ||
|
||
[return: MarshalAs(UnmanagedType.Interface)] | ||
ISetupInstance GetInstanceForPath([MarshalAs(UnmanagedType.LPWStr), In] string path); | ||
|
||
[return: MarshalAs(UnmanagedType.Interface)] | ||
IEnumSetupInstances EnumAllInstances(); | ||
} | ||
|
||
[Guid("B41463C3-8866-43B5-BC33-2B0676F7F42E")] | ||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] | ||
[ComImport] | ||
public interface ISetupInstance | ||
{ | ||
} | ||
|
||
[Guid("89143C9A-05AF-49B0-B717-72E218A2185C")] | ||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] | ||
[ComImport] | ||
public interface ISetupInstance2 : ISetupInstance | ||
{ | ||
[return: MarshalAs(UnmanagedType.BStr)] | ||
string GetInstanceId(); | ||
|
||
[return: MarshalAs(UnmanagedType.Struct)] | ||
System.Runtime.InteropServices.ComTypes.FILETIME GetInstallDate(); | ||
|
||
[return: MarshalAs(UnmanagedType.BStr)] | ||
string GetInstallationName(); | ||
|
||
[return: MarshalAs(UnmanagedType.BStr)] | ||
string GetInstallationPath(); | ||
|
||
[return: MarshalAs(UnmanagedType.BStr)] | ||
string GetInstallationVersion(); | ||
|
||
[return: MarshalAs(UnmanagedType.BStr)] | ||
string GetDisplayName([MarshalAs(UnmanagedType.U4), In] int lcid); | ||
|
||
[return: MarshalAs(UnmanagedType.BStr)] | ||
string GetDescription([MarshalAs(UnmanagedType.U4), In] int lcid); | ||
|
||
[return: MarshalAs(UnmanagedType.BStr)] | ||
string ResolvePath([MarshalAs(UnmanagedType.LPWStr), In] string pwszRelativePath); | ||
|
||
[return: MarshalAs(UnmanagedType.U4)] | ||
InstanceState GetState(); | ||
|
||
[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UNKNOWN)] | ||
ISetupPackageReference[] GetPackages(); | ||
|
||
ISetupPackageReference GetProduct(); | ||
|
||
[return: MarshalAs(UnmanagedType.BStr)] | ||
string GetProductPath(); | ||
|
||
[return: MarshalAs(UnmanagedType.VariantBool)] | ||
bool IsLaunchable(); | ||
|
||
[return: MarshalAs(UnmanagedType.VariantBool)] | ||
bool IsComplete(); | ||
|
||
[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UNKNOWN)] | ||
ISetupPropertyStore GetProperties(); | ||
|
||
[return: MarshalAs(UnmanagedType.BStr)] | ||
string GetEnginePath(); | ||
} | ||
|
||
[Guid("DA8D8A16-B2B6-4487-A2F1-594CCCCD6BF5")] | ||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] | ||
[ComImport] | ||
public interface ISetupPackageReference | ||
{ | ||
|
||
[return: MarshalAs(UnmanagedType.BStr)] | ||
string GetId(); | ||
|
||
[return: MarshalAs(UnmanagedType.BStr)] | ||
string GetVersion(); | ||
|
||
[return: MarshalAs(UnmanagedType.BStr)] | ||
string GetChip(); | ||
|
||
[return: MarshalAs(UnmanagedType.BStr)] | ||
string GetLanguage(); | ||
|
||
[return: MarshalAs(UnmanagedType.BStr)] | ||
string GetBranch(); | ||
|
||
[return: MarshalAs(UnmanagedType.BStr)] | ||
string GetType(); | ||
|
||
[return: MarshalAs(UnmanagedType.BStr)] | ||
string GetUniqueId(); | ||
|
||
[return: MarshalAs(UnmanagedType.VariantBool)] | ||
bool GetIsExtension(); | ||
} | ||
|
||
[Guid("c601c175-a3be-44bc-91f6-4568d230fc83")] | ||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] | ||
[ComImport] | ||
public interface ISetupPropertyStore | ||
{ | ||
|
||
[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)] | ||
string[] GetNames(); | ||
|
||
object GetValue([MarshalAs(UnmanagedType.LPWStr), In] string pwszName); | ||
} | ||
|
||
[Guid("42843719-DB4C-46C2-8E7C-64F1816EFD5B")] | ||
[CoClass(typeof(SetupConfigurationClass))] | ||
[ComImport] | ||
public interface SetupConfiguration : ISetupConfiguration2, ISetupConfiguration | ||
{ | ||
} | ||
|
||
[Guid("177F0C4A-1CD3-4DE7-A32C-71DBBB9FA36D")] | ||
[ClassInterface(ClassInterfaceType.None)] | ||
[ComImport] | ||
public class SetupConfigurationClass | ||
{ | ||
} | ||
|
||
public static class Main | ||
{ | ||
public static void Query() | ||
{ | ||
ISetupConfiguration query = new SetupConfiguration(); | ||
ISetupConfiguration2 query2 = (ISetupConfiguration2)query; | ||
IEnumSetupInstances e = query2.EnumAllInstances(); | ||
|
||
int pceltFetched; | ||
ISetupInstance2[] rgelt = new ISetupInstance2[1]; | ||
while (true) | ||
{ | ||
e.Next(1, rgelt, out pceltFetched); | ||
if (pceltFetched <= 0) | ||
{ | ||
Console.WriteLine("No usable installation of VS2017 found"); | ||
return; | ||
} | ||
if (CheckInstance(rgelt[0])) | ||
return; | ||
} | ||
} | ||
|
||
private static bool CheckInstance(ISetupInstance2 setupInstance2) | ||
{ | ||
// Visual Studio Community 2017 component directory: | ||
// https://www.visualstudio.com/en-us/productinfo/vs2017-install-product-Community.workloads | ||
|
||
string path = setupInstance2.GetInstallationPath(); | ||
Console.WriteLine(String.Format("Found VS2017 installation at: {0}", path)); | ||
|
||
bool hasMSBuild = false; | ||
bool hasVCTools = false; | ||
uint Win10SDKVer = 0; | ||
bool hasWin8SDK = false; | ||
|
||
foreach (ISetupPackageReference package in setupInstance2.GetPackages()) | ||
{ | ||
const string Win10SDKPrefix = "Microsoft.VisualStudio.Component.Windows10SDK."; | ||
|
||
string id = package.GetId(); | ||
if (id == "Microsoft.VisualStudio.VC.MSBuild.Base") | ||
hasMSBuild = true; | ||
else if (id == "Microsoft.VisualStudio.Component.VC.Tools.x86.x64") | ||
hasVCTools = true; | ||
else if (id.StartsWith(Win10SDKPrefix)) | ||
Win10SDKVer = Math.Max(Win10SDKVer, UInt32.Parse(id.Substring(Win10SDKPrefix.Length))); | ||
else if (id == "Microsoft.VisualStudio.Component.Windows81SDK") | ||
hasWin8SDK = true; | ||
else | ||
continue; | ||
|
||
Console.WriteLine(String.Format(" - Found {0}", id)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
unreachable? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is reached when any of the if conditions above is true There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, ofcourse. I misread the code. |
||
} | ||
|
||
if (!hasMSBuild) | ||
Console.WriteLine(" - Missing Visual Studio C++ core features (Microsoft.VisualStudio.VC.MSBuild.Base)"); | ||
if (!hasVCTools) | ||
Console.WriteLine(" - Missing VC++ 2017 v141 toolset (x86,x64) (Microsoft.VisualStudio.Component.VC.Tools.x86.x64)"); | ||
if ((Win10SDKVer == 0) && (!hasWin8SDK)) | ||
Console.WriteLine(" - Missing a Windows SDK (Microsoft.VisualStudio.Component.Windows10SDK.* or Microsoft.VisualStudio.Component.Windows81SDK)"); | ||
|
||
if (hasMSBuild && hasVCTools) | ||
{ | ||
string setPath = String.Format("set \"VS2017_INSTALL={0}\"", path); | ||
if (Win10SDKVer > 0) | ||
{ | ||
Console.WriteLine(" - Using this installation with Windows 10 SDK"); | ||
string[] lines = { setPath, String.Format("set \"VS2017_SDK=10.0.{0}.0\"", Win10SDKVer) }; | ||
System.IO.File.WriteAllLines(@"Set_VS2017.bat", lines); | ||
return true; | ||
} | ||
else if (hasWin8SDK) | ||
{ | ||
Console.WriteLine(" - Using this installation with Windows 8.1 SDK"); | ||
string[] lines = { setPath, "set \"VS2017_SDK=8.1\"" }; | ||
System.IO.File.WriteAllLines(@"Set_VS2017.bat", lines); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This smell bad... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this be done differently? |
||
return true; | ||
} | ||
} | ||
|
||
Console.WriteLine(" - Some required components are missing, not using this installation"); | ||
return false; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -84,6 +84,10 @@ def SetupScript(self, target_arch): | |
# vcvars32, which it can only find if VS??COMNTOOLS is set, which it | ||
# isn't always. | ||
if target_arch == 'x86': | ||
if self.short_name == '2017': | ||
return [os.path.normpath( | ||
os.path.join(self.path, 'Common7/Tools/VsDevCmd.bat')), '/no_logo', | ||
'/arch=x86'] | ||
if self.short_name >= '2013' and self.short_name[-1] != 'e' and ( | ||
os.environ.get('PROCESSOR_ARCHITECTURE') == 'AMD64' or | ||
os.environ.get('PROCESSOR_ARCHITEW6432') == 'AMD64'): | ||
|
@@ -96,6 +100,10 @@ def SetupScript(self, target_arch): | |
os.path.join(self.path, 'Common7/Tools/vsvars32.bat'))] | ||
else: | ||
assert target_arch == 'x64' | ||
if self.short_name == '2017': | ||
return [os.path.normpath( | ||
os.path.join(self.path, 'Common7/Tools/VsDevCmd.bat')), '/no_logo', | ||
'/arch=x64'] | ||
arg = 'x86_amd64' | ||
# Use the 64-on-64 compiler if we're not using an express | ||
# edition and we're running on a 64bit OS. | ||
|
@@ -226,6 +234,15 @@ def _CreateVersion(name, path, sdk_based=False): | |
if path: | ||
path = os.path.normpath(path) | ||
versions = { | ||
'2017': VisualStudioVersion('2017', | ||
'Visual Studio 2017', | ||
solution_version='12.00', | ||
project_version='14.0', | ||
flat_sln=False, | ||
uses_vcxproj=True, | ||
path=path, | ||
sdk_based=sdk_based, | ||
default_toolset='v141'), | ||
'2015': VisualStudioVersion('2015', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So this is a de-novo patch, not based on the strategy in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Node-gyp is very adverse to floating patches, but that is not the case here. I'd rather have the floating patch and not hack gyp. This patch is small enough to be reviewed here, and contained in a git commit so it can be easily reverted if a different approach lands upstream. |
||
'Visual Studio 2015', | ||
solution_version='12.00', | ||
|
@@ -346,6 +363,7 @@ def _DetectVisualStudioVersions(versions_to_check, force_express): | |
2012(e) - Visual Studio 2012 (11) | ||
2013(e) - Visual Studio 2013 (12) | ||
2015 - Visual Studio 2015 (14) | ||
2017 - Visual Studio 2017 (15) | ||
Where (e) is e for express editions of MSVS and blank otherwise. | ||
""" | ||
version_to_year = { | ||
|
@@ -355,6 +373,7 @@ def _DetectVisualStudioVersions(versions_to_check, force_express): | |
'11.0': '2012', | ||
'12.0': '2013', | ||
'14.0': '2015', | ||
'15.0': '2017', | ||
} | ||
versions = [] | ||
for version in versions_to_check: | ||
|
@@ -395,6 +414,17 @@ def _DetectVisualStudioVersions(versions_to_check, force_express): | |
versions.append(_CreateVersion(version_to_year[version] + 'e', | ||
os.path.join(path, '..'), sdk_based=True)) | ||
|
||
if version == '15.0': | ||
# The VC++ 2017 install location needs to be located using COM instead of | ||
# the registry. For details see: | ||
# https://blogs.msdn.microsoft.com/heaths/2016/09/15/changes-to-visual-studio-15-setup/ | ||
# For now we use a hardcoded default with an environment variable | ||
# override. | ||
path = r'C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional' | ||
path = os.environ.get('vs2017_install', path) | ||
if os.path.exists(path): | ||
versions.append(_CreateVersion('2017', path)) | ||
|
||
return versions | ||
|
||
|
||
|
@@ -410,7 +440,7 @@ def SelectVisualStudioVersion(version='auto', allow_fallback=True): | |
if version == 'auto': | ||
version = os.environ.get('GYP_MSVS_VERSION', 'auto') | ||
version_map = { | ||
'auto': ('14.0', '12.0', '10.0', '9.0', '8.0', '11.0'), | ||
'auto': ('15.0', '14.0', '12.0', '10.0', '9.0', '8.0', '11.0'), | ||
'2005': ('8.0',), | ||
'2005e': ('8.0',), | ||
'2008': ('9.0',), | ||
|
@@ -422,6 +452,7 @@ def SelectVisualStudioVersion(version='auto', allow_fallback=True): | |
'2013': ('12.0',), | ||
'2013e': ('12.0',), | ||
'2015': ('14.0',), | ||
'2017': ('15.0',), | ||
} | ||
override_path = os.environ.get('GYP_MSVS_OVERRIDE_PATH') | ||
if override_path: | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use
var
to prevent redundancy?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're trying to support Windows 7/2008R2 with the tools that it ships with by default, that means C# version 2.
var
was only introduced in version 3.