Skip to content
Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions gyp/pylib/gyp/generator/msvs.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ def _import_OrderedDict():
'msvs_enable_winrt',
'msvs_requires_importlibrary',
'msvs_enable_winphone',
'msvs_enable_marmasm',
'msvs_application_type_revision',
'msvs_target_platform_version',
'msvs_target_platform_minversion',
Expand Down Expand Up @@ -3362,7 +3363,8 @@ def _GenerateMSBuildProject(project, options, version, generator_flags):
content += _GetMSBuildLocalProperties(project.msbuild_toolset)
content += import_cpp_props_section
content += import_masm_props_section
content += import_marmasm_props_section
if spec.get('msvs_enable_marmasm'):
content += import_marmasm_props_section
content += _GetMSBuildExtensions(props_files_of_rules)
content += _GetMSBuildPropertySheets(configurations)
content += macro_section
Expand All @@ -3375,7 +3377,8 @@ def _GenerateMSBuildProject(project, options, version, generator_flags):
content += _GetMSBuildProjectReferences(project)
content += import_cpp_targets_section
content += import_masm_targets_section
content += import_marmasm_targets_section
if spec.get('msvs_enable_marmasm'):
content += import_marmasm_targets_section
content += _GetMSBuildExtensionTargets(targets_files_of_rules)

if spec.get('msvs_external_builder'):
Expand Down
88 changes: 29 additions & 59 deletions lib/Find-VS2017.cs → lib/Find-VisualStudio.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@
// 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()}"
// powershell -ExecutionPolicy Unrestricted -Command "Add-Type -Path Find-VisualStudio.cs; [VisualStudioConfiguration.Main]::PrintJson()"
// This script needs to be compatible with PowerShell v2 to run on Windows 2008R2 and Windows 7.

using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Collections.Generic;

namespace VisualStudioConfiguration
{
Expand Down Expand Up @@ -184,90 +187,57 @@ public class SetupConfigurationClass

public static class Main
{
public static void Query()
public static void PrintJson()
{
ISetupConfiguration query = new SetupConfiguration();
ISetupConfiguration2 query2 = (ISetupConfiguration2)query;
IEnumSetupInstances e = query2.EnumAllInstances();

int pceltFetched;
ISetupInstance2[] rgelt = new ISetupInstance2[1];
StringBuilder log = new StringBuilder();
List<string> instances = new List<string>();
while (true)
{
e.Next(1, rgelt, out pceltFetched);
if (pceltFetched <= 0)
{
Console.WriteLine(String.Format("{{\"log\":\"{0}\"}}", log.ToString()));
Console.WriteLine(String.Format("[{0}]", string.Join(",", instances.ToArray())));
return;
}
if (CheckInstance(rgelt[0], ref log))
return;

instances.Add(InstanceJson(rgelt[0]));
}
}

private static bool CheckInstance(ISetupInstance2 setupInstance2, ref StringBuilder log)
private static string JsonString(string s)
{
// Visual Studio Community 2017 component directory:
// https://www.visualstudio.com/en-us/productinfo/vs2017-install-product-Community.workloads
return "\"" + s.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\"";
}

string path = setupInstance2.GetInstallationPath().Replace("\\", "\\\\");
log.Append(String.Format("Found installation at: {0}\\n", path));
private static string InstanceJson(ISetupInstance2 setupInstance2)
{
// Visual Studio component directory:
// https://docs.microsoft.com/en-us/visualstudio/install/workload-and-component-ids

bool hasMSBuild = false;
bool hasVCTools = false;
uint Win10SDKVer = 0;
bool hasWin8SDK = false;
StringBuilder json = new StringBuilder();
json.Append("{");

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)) {
string[] parts = id.Substring(Win10SDKPrefix.Length).Split('.');
if (parts.Length > 1 && parts[1] != "Desktop")
continue;
uint foundSdkVer;
if (UInt32.TryParse(parts[0], out foundSdkVer))
Win10SDKVer = Math.Max(Win10SDKVer, foundSdkVer);
} else if (id == "Microsoft.VisualStudio.Component.Windows81SDK")
hasWin8SDK = true;
else
continue;

log.Append(String.Format(" - Found {0}\\n", id));
}
string path = JsonString(setupInstance2.GetInstallationPath());
json.Append(String.Format("\"path\":{0},", path));

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");
string version = JsonString(setupInstance2.GetInstallationVersion());
json.Append(String.Format("\"version\":{0},", version));

if (hasMSBuild && hasVCTools)
List<string> packages = new List<string>();
foreach (ISetupPackageReference package in setupInstance2.GetPackages())
{
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;
}
string id = JsonString(package.GetId());
packages.Add(id);
}
json.Append(String.Format("\"packages\":[{0}]", string.Join(",", packages.ToArray())));

log.Append(" - Some required components are missing, not using this installation\\n");
return false;
json.Append("}");
return json.ToString();
}
}
}
76 changes: 7 additions & 69 deletions lib/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ var fs = require('graceful-fs')
, glob = require('glob')
, log = require('npmlog')
, which = require('which')
, exec = require('child_process').exec
, win = process.platform === 'win32'

exports.usage = 'Invokes `' + (win ? 'msbuild' : 'make') + '` and builds the module'
Expand Down Expand Up @@ -96,7 +95,11 @@ function build (gyp, argv, callback) {

function doWhich () {
// On Windows use msbuild provided by node-gyp configure
if (win && config.variables.msbuild_path) {
if (win) {
if (!config.variables.msbuild_path) {
return callback(new Error(
'MSBuild is not set, please run `node-gyp configure`.'))
}
command = config.variables.msbuild_path
log.verbose('using MSBuild:', command)
doBuild()
Expand All @@ -105,80 +108,15 @@ function build (gyp, argv, callback) {
// First make sure we have the build command in the PATH
which(command, function (err, execPath) {
if (err) {
if (win && /not found/.test(err.message)) {
// On windows and no 'msbuild' found. Let's guess where it is
findMsbuild()
} else {
// Some other error or 'make' not found on Unix, report that to the user
callback(err)
}
// Some other error or 'make' not found on Unix, report that to the user
callback(err)
return
}
log.verbose('`which` succeeded for `' + command + '`', execPath)
doBuild()
})
}

/**
* Search for the location of "msbuild.exe" file on Windows.
*/

function findMsbuild () {
log.verbose('could not find "msbuild.exe" in PATH - finding location in registry')
var notfoundErr = 'Can\'t find "msbuild.exe". Do you have Microsoft Visual Studio C++ 2008+ installed?'
var cmd = 'reg query "HKLM\\Software\\Microsoft\\MSBuild\\ToolsVersions" /s'
if (process.arch !== 'ia32')
cmd += ' /reg:32'
exec(cmd, function (err, stdout) {
if (err) {
return callback(new Error(err.message + '\n' + notfoundErr))
}
var reVers = /ToolsVersions\\([^\\]+)$/i
, rePath = /\r\n[ \t]+MSBuildToolsPath[ \t]+REG_SZ[ \t]+([^\r]+)/i
, msbuilds = []
, r
, msbuildPath
stdout.split('\r\n\r\n').forEach(function(l) {
if (!l) return
l = l.trim()
if (r = reVers.exec(l.substring(0, l.indexOf('\r\n')))) {
var ver = parseFloat(r[1], 10)
if (ver >= 3.5) {
if (r = rePath.exec(l)) {
msbuilds.push({
version: ver,
path: r[1]
})
}
}
}
})
msbuilds.sort(function (x, y) {
return (x.version < y.version ? -1 : 1)
})
;(function verifyMsbuild () {
if (!msbuilds.length) return callback(new Error(notfoundErr))
msbuildPath = path.resolve(msbuilds.pop().path, 'msbuild.exe')
fs.stat(msbuildPath, function (err) {
if (err) {
if (err.code == 'ENOENT') {
if (msbuilds.length) {
return verifyMsbuild()
} else {
callback(new Error(notfoundErr))
}
} else {
callback(err)
}
return
}
command = msbuildPath
doBuild()
})
})()
})
}

/**
* Actually spawn the process and compile the module.
*/
Expand Down
67 changes: 18 additions & 49 deletions lib/configure.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ var fs = require('graceful-fs')
, win = process.platform === 'win32'
, findNodeDirectory = require('./find-node-directory')
, msgFormat = require('util').format
, logWithPrefix = require('./util').logWithPrefix
if (win)
var findVS2017 = require('./find-vs2017')
var findVisualStudio = require('./find-visualstudio')

exports.usage = 'Generates ' + (win ? 'MSVC project files' : 'a Makefile') + ' for the current module'

Expand Down Expand Up @@ -82,22 +83,16 @@ function configure (gyp, argv, callback) {
mkdirp(buildDir, function (err, isNew) {
if (err) return callback(err)
log.verbose('build dir', '"build" dir needed to be created?', isNew)
if (win && (!gyp.opts.msvs_version || gyp.opts.msvs_version === '2017')) {
findVS2017(function (err, vsSetup) {
if (err) {
log.verbose('Not using VS2017:', err.message)
createConfigFile()
} else {
createConfigFile(null, vsSetup)
}
})
if (win) {
findVisualStudio(release.semver, gyp.opts.msvs_version,
createConfigFile)
} else {
createConfigFile()
}
})
}

function createConfigFile (err, vsSetup) {
function createConfigFile (err, vsInfo) {
if (err) return callback(err)

var configFilename = 'config.gypi'
Expand Down Expand Up @@ -144,17 +139,18 @@ function configure (gyp, argv, callback) {
// disable -T "thin" static archives by default
variables.standalone_static_library = gyp.opts.thin ? 0 : 1

if (vsSetup) {
// GYP doesn't (yet) have support for VS2017, so we force it to VS2015
// to avoid pulling a floating patch that has not landed upstream.
// Ref: https://chromium-review.googlesource.com/#/c/433540/
gyp.opts.msvs_version = '2015'
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')
if (win) {
process.env['GYP_MSVS_VERSION'] = Math.min(vsInfo.versionYear, 2015)
process.env['GYP_MSVS_OVERRIDE_PATH'] = vsInfo.path
defaults['msbuild_toolset'] = vsInfo.toolset
if (vsInfo.sdk) {
defaults['msvs_windows_target_platform_version'] = vsInfo.sdk
}
if (vsInfo.versionMajor > 15 ||
(vsInfo.versionMajor === 15 && vsInfo.versionMajor >= 9)) {
defaults['msvs_enable_marmasm'] = 1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO this is only needed if variables.target_arch == 'arm64'

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a fixup, thanks @refack!

}
variables['msbuild_path'] = vsInfo.msBuild
}

// loop through the rest of the opts and add the unknown ones as variables.
Expand Down Expand Up @@ -220,20 +216,6 @@ function configure (gyp, argv, callback) {
}
}

function hasMsvsVersion () {
return argv.some(function (arg) {
return arg.indexOf('msvs_version') === 0
})
}

if (win && !hasMsvsVersion()) {
if ('msvs_version' in gyp.opts) {
argv.push('-G', 'msvs_version=' + gyp.opts.msvs_version)
} else {
argv.push('-G', 'msvs_version=auto')
}
}

// include all the ".gypi" files that were found
configs.forEach(function (config) {
argv.push('-I', config)
Expand Down Expand Up @@ -644,16 +626,3 @@ function findPython (configPython, callback) {
var finder = new PythonFinder(configPython, callback)
finder.findPython()
}

function logWithPrefix (log, prefix) {
function setPrefix(logFunction) {
return (...args) => logFunction.apply(null, [prefix, ...args])
}
return {
silly: setPrefix(log.silly),
verbose: setPrefix(log.verbose),
info: setPrefix(log.info),
warn: setPrefix(log.warn),
error: setPrefix(log.error),
}
}
Loading