-
Notifications
You must be signed in to change notification settings - Fork 1.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: find and setup for VS2017 #1130
Changes from 3 commits
1f79c98
2dd811b
034a330
5a06bef
5faa488
e1cc9ec
4860d72
e353a28
4d0b91f
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 |
---|---|---|
@@ -0,0 +1,262 @@ | ||
// 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(); | ||
|
||
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]; | ||
StringBuilder log = new StringBuilder(); | ||
while (true) | ||
{ | ||
e.Next(1, rgelt, out pceltFetched); | ||
if (pceltFetched <= 0) | ||
{ | ||
Console.WriteLine(String.Format("{{\"log\":\"{0}\"}}", log.ToString())); | ||
return; | ||
} | ||
if (CheckInstance(rgelt[0], ref log)) | ||
return; | ||
} | ||
} | ||
|
||
private static bool CheckInstance(ISetupInstance2 setupInstance2, ref StringBuilder log) | ||
{ | ||
// Visual Studio Community 2017 component directory: | ||
// https://www.visualstudio.com/en-us/productinfo/vs2017-install-product-Community.workloads | ||
|
||
string path = setupInstance2.GetInstallationPath().Replace("\\", "\\\\"); | ||
log.Append(String.Format("Found installation at: {0}\\n", 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))); | ||
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. Bug found with new SDK #1144 |
||
else if (id == "Microsoft.VisualStudio.Component.Windows81SDK") | ||
hasWin8SDK = true; | ||
else | ||
continue; | ||
|
||
log.Append(String.Format(" - Found {0}\\n", id)); | ||
} | ||
|
||
if (!hasMSBuild) | ||
log.Append(" - Missing Visual Studio C++ core features (Microsoft.VisualStudio.VC.MSBuild.Base)\\n"); | ||
if (!hasVCTools) | ||
log.Append(" - Missing VC++ 2017 v141 toolset (x86,x64) (Microsoft.VisualStudio.Component.VC.Tools.x86.x64)\\n"); | ||
if ((Win10SDKVer == 0) && (!hasWin8SDK)) | ||
log.Append(" - Missing a Windows SDK (Microsoft.VisualStudio.Component.Windows10SDK.* or Microsoft.VisualStudio.Component.Windows81SDK)\\n"); | ||
|
||
if (hasMSBuild && hasVCTools) | ||
{ | ||
if (Win10SDKVer > 0) | ||
{ | ||
log.Append(" - Using this installation with Windows 10 SDK"/*\\n*/); | ||
Console.WriteLine(String.Format("{{\"log\":\"{0}\",\"path\":\"{1}\",\"sdk\":\"10.0.{2}.0\"}}", log.ToString(), path, Win10SDKVer)); | ||
return true; | ||
} | ||
else if (hasWin8SDK) | ||
{ | ||
log.Append(" - Using this installation with Windows 8.1 SDK"/*\\n*/); | ||
Console.WriteLine(String.Format("{{\"log\":\"{0}\",\"path\":\"{1}\",\"sdk\":\"8.1\"}}", log.ToString(), path)); | ||
return true; | ||
} | ||
} | ||
|
||
log.Append(" - Some required components are missing, not using this installation\\n"); | ||
return false; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,9 +19,11 @@ var fs = require('graceful-fs') | |
, cp = require('child_process') | ||
, extend = require('util')._extend | ||
, processRelease = require('./process-release') | ||
, win = process.platform == 'win32' | ||
, win = process.platform === 'win32' | ||
, findNodeDirectory = require('./find-node-directory') | ||
, msgFormat = require('util').format | ||
if (win) | ||
var findVS2017 = require('./find-vs2017') | ||
|
||
exports.usage = 'Generates ' + (win ? 'MSVC project files' : 'a Makefile') + ' for the current module' | ||
|
||
|
@@ -137,6 +139,18 @@ function configure (gyp, argv, callback) { | |
// disable -T "thin" static archives by default | ||
variables.standalone_static_library = gyp.opts.thin ? 0 : 1 | ||
|
||
if (win && !(gyp.opts.msvs_version && gyp.opts.msvs_version !== '2017')) { | ||
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. would you mind inverting this? reads really badly. |
||
const vsSetup = findVS2017() | ||
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.
|
||
if (vsSetup) { | ||
gyp.opts.msvs_version = '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. are we forcing this to make GYP happy, or is this (and the next line) a mistake? 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. We are forcing this to make GYP happy, and to avoid pulling https://chromium-review.googlesource.com/#/c/433540/ (which did not land yet) as a floating patch, since floating patches seem to be avoided here. |
||
process.env['GYP_MSVS_VERSION'] = 2015 | ||
process.env['GYP_MSVS_OVERRIDE_PATH'] = vsSetup.path | ||
defaults['msbuild_toolset'] = 'v141' | ||
defaults['msvs_windows_target_platform_version'] = vsSetup.sdk | ||
variables['msbuild_path'] = path.join(vsSetup.path, 'MSBuild', '15.0', 'Bin', 'MSBuild.exe') | ||
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. Can you wrap this at 80 columns? |
||
} | ||
} | ||
|
||
// loop through the rest of the opts and add the unknown ones as variables. | ||
// this allows for module-specific configure flags like: | ||
// | ||
|
@@ -317,9 +331,9 @@ function configure (gyp, argv, callback) { | |
} | ||
|
||
/** | ||
* Returns the first file or directory from an array of candidates that is | ||
* Returns the first file or directory from an array of candidates that is | ||
* readable by the current user, or undefined if none of the candidates are | ||
* readable. | ||
* readable. | ||
*/ | ||
function findAccessibleSync (logprefix, dir, candidates) { | ||
for (var next = 0; next < candidates.length; next++) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
const log = require('npmlog') | ||
, execSync = require('child_process').execSync | ||
, path = require('path') | ||
|
||
var hasCache = false | ||
, cache = null | ||
|
||
function findVS2017() { | ||
if (hasCache) | ||
return cache | ||
|
||
hasCache = true | ||
|
||
const ps = 'PowerShell -ExecutionPolicy Unrestricted -Command ' | ||
const csFile = path.join(__dirname, 'Find-VS2017.cs') | ||
const psQuery = ps + '"&{Add-Type -Path \'' + csFile + '\'; [VisualStudioConfiguration.Main]::Query()}" 2>&1' | ||
|
||
var vsSetup | ||
try { | ||
const vsSetupRaw = execSync(psQuery, { encoding: 'utf8' }) | ||
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.
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. sorry, I mean, |
||
log.silly('find vs2017', 'vsSetupRaw:', vsSetupRaw) | ||
vsSetup = JSON.parse(vsSetupRaw) | ||
log.silly('find vs2017', 'vsSetup:', vsSetup) | ||
} catch (e) { | ||
log.silly('find vs2017', e) | ||
log.verbose('find vs2017', 'could not use PowerShell to find VS2017') | ||
return cache | ||
} | ||
|
||
if (vsSetup && vsSetup.log) | ||
log.verbose('find vs2017', vsSetup.log.trimRight()) | ||
|
||
if (!vsSetup || !vsSetup.path || !vsSetup.sdk) { | ||
log.verbose('find vs2017', 'no usable installation found') | ||
return cache | ||
} | ||
|
||
cache = { | ||
"path": vsSetup.path, | ||
"sdk": vsSetup.sdk | ||
} | ||
|
||
log.verbose('find vs2017', 'using installation:', cache.path) | ||
return cache | ||
} | ||
|
||
module.exports = findVS2017 |
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.
does this file need source attribution and/or copyright? or is it ours?
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.
This was submitted by @refack in #1103 , I believe it was adapted from the python COM API by @bzoz in #1101 , which in turn got the GUIDs and API from the nuget package upstream. @refack can you confim?
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.
I wrote it myself. GUIDs extracted from interop
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.
Please add
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.
I recommend using updated file https://github.com/node4good/windows-autoconf/blob/master/tools/GetVS2017Configuration.cs