diff --git a/.gitignore b/.gitignore index 6748492014..b62fa53e11 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ gyp/test node_modules test/.node-gyp +!test/node_modules +build/ diff --git a/lib/build.js b/lib/build.js index 0374fbc810..6c58167dcf 100644 --- a/lib/build.js +++ b/lib/build.js @@ -14,7 +14,9 @@ var fs = require('graceful-fs') , mkdirp = require('mkdirp') , exec = require('child_process').exec , processRelease = require('./process-release') - , win = process.platform == 'win32' + , win = process.platform === 'win32'; +if (win) + var findVS = require('windows-autoconf') exports.usage = 'Invokes `' + (win ? 'msbuild' : 'make') + '` and builds the module' @@ -106,7 +108,7 @@ function build (gyp, argv, callback) { 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 + log.verbose('could not find "msbuild.exe" in PATH - finding location in registry') findMsbuild() } else { // Some other error or 'make' not found on Unix, report that to the user @@ -122,61 +124,18 @@ function build (gyp, argv, callback) { /** * 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, stderr) { - if (err) { - return callback(new Error(err.message + '\n' + notfoundErr)) + var notfoundErr = 'Can\'t find "msbuild.exe". Do you have Microsoft Visual Studio installed?' + try { + var msbuild_path = findVS.locateMsbuild() + if (!msbuild_path) { + return callback(new Error(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, stat) { - if (err) { - if (err.code == 'ENOENT') { - if (msbuilds.length) { - return verifyMsbuild() - } else { - callback(new Error(notfoundErr)) - } - } else { - callback(err) - } - return - } - command = msbuildPath - copyNodeLib() - }) - })() - }) + } catch (e) { + return callback(new Error(err.message + '\n' + notfoundErr)) + } + command = msbuild_path + copyNodeLib() } /** diff --git a/lib/configure.js b/lib/configure.js index d52b2902b0..503bda81d4 100644 --- a/lib/configure.js +++ b/lib/configure.js @@ -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 findVS = require('windows-autoconf') exports.usage = 'Generates ' + (win ? 'MSVC project files' : 'a Makefile') + ' for the current module' @@ -39,15 +41,13 @@ function configure (gyp, argv, callback) { callback(err) } else { python = found - getNodeDir() + // 'python' should be set by now + process.env.PYTHON = python + getNodeDir() } }) function getNodeDir () { - - // 'python' should be set by now - process.env.PYTHON = python - if (gyp.opts.nodedir) { // --nodedir was specified. use that for the dev files nodeDir = gyp.opts.nodedir.replace(/^~/, osenv.home()) @@ -90,6 +90,24 @@ function configure (gyp, argv, callback) { }) } + function findVisualStudio2017 (defaults) { + if (gyp.opts.msvs_version && gyp.opts.msvs_version !== '2017') + return + + try { + var vsSetup = findVS.getVS2017Setup() + if (!vsSetup || !vsSetup.InstallationPath) return + } catch (_) { + return + } + + gyp.opts.msvs_version = '2015' + process.env['GYP_MSVS_VERSION'] = 2015 + process.env['GYP_MSVS_OVERRIDE_PATH'] = vsSetup.InstallationPath + defaults['msbuild_toolset'] = 'v141' + defaults['msvs_windows_target_platform_version'] = vsSetup.SDK + } + function createConfigFile (err) { if (err) return callback(err) @@ -137,6 +155,9 @@ function configure (gyp, argv, callback) { // disable -T "thin" static archives by default variables.standalone_static_library = gyp.opts.thin ? 0 : 1 + if (win) + findVisualStudio2017(defaults) + // loop through the rest of the opts and add the unknown ones as variables. // this allows for module-specific configure flags like: // @@ -201,7 +222,7 @@ function configure (gyp, argv, callback) { } function hasMsvsVersion () { - return argv.some(function (arg) { + return argv.find(function (arg) { return arg.indexOf('msvs_version') === 0 }) } @@ -317,9 +338,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++) { diff --git a/package.json b/package.json index 068271addf..86386df3c5 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "rimraf": "2", "semver": "~5.3.0", "tar": "^2.0.0", + "windows-autoconf": "^1.9.7", "which": "1" }, "engines": {