diff --git a/lib/configure.js b/lib/configure.js index 2ff476deb1..0a08abe0e2 100644 --- a/lib/configure.js +++ b/lib/configure.js @@ -1,6 +1,7 @@ module.exports = exports = configure module.exports.test = { findAccessibleSync: findAccessibleSync, - findPython: findPython } + findPython: findPython, + nodeModulesVersion: nodeModulesVersion } /** * Module dependencies. @@ -127,6 +128,18 @@ function configure (gyp, argv, callback) { // set the target_arch variable variables.target_arch = gyp.opts.arch || process.arch || 'ia32' + log.verbose('build/' + configFilename, + 'target arch: ' + variables.target_arch) + + // set the target_platform variable + variables.target_platform = process.platform + log.verbose('build/' + configFilename, + 'target platform: ' + variables.target_platform) + + // set the target modules version + variables.target_modules_version = nodeModulesVersion(nodeDir) + log.verbose('build/' + configFilename, + 'modules version: ' + variables.target_modules_version) // set the node development directory variables.nodedir = nodeDir @@ -311,6 +324,42 @@ function configure (gyp, argv, callback) { } +/** + * Returns value of NODE_MODULE_VERSION define + * from Node source code in specified directory + * for specified Node version + */ +function nodeModulesVersion(nodeDir) { + var versionStr = path.basename(nodeDir) + + // parse version from the base name of nodeDir + // probably removing optional `releaseName-` prefix + var nodeVersion = semver.valid(versionStr) + || semver.valid(versionStr.substr(versionStr.indexOf('-') + 1)) + + if (!nodeVersion) { + throw new Error('Can\'t extract target version from ' + nodeDir) + } + + // NODE_MODULE_VERSION may be defined in different files + // depending on the target Node.js version + if (semver.gte(nodeVersion, '3.0.0')) { + nodeVersion = 'include/node/node_version.h' + } else if (semver.gt(nodeVersion, '0.11.4')) { + nodeVersion = 'src/node_version.h' + } else { + nodeVersion = 'src/node.h' + } + nodeVersion = path.join(nodeDir, nodeVersion) + + var modulesVersion = fs.readFileSync(nodeVersion, { encoding: 'utf8' }) + .match(/#define\s+NODE_MODULE_VERSION\s+\(?(\S+)\)?/) + if (!modulesVersion) { + throw new Error('#define NODE_MODULE_VERSION not found in ' + nodeVersion) + } + return parseInt(modulesVersion[1]).toString() +} + /** * 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 diff --git a/test/test-node-modules-version.js b/test/test-node-modules-version.js new file mode 100644 index 0000000000..08a4c46dfa --- /dev/null +++ b/test/test-node-modules-version.js @@ -0,0 +1,34 @@ +'use strict' + +var test = require('tape') +var path = require('path') +var semver = require('semver') +var processRelease = require('../lib/process-release') +var configure = require('../lib/configure') + +var gyp = require('../lib/node-gyp')() // for gyp.devDir +gyp.parseArgv([]) // to initialize gyp.opts + +test('modules version for the current release', function (t) { + t.plan(1) + + var release = processRelease([], gyp, process.version) + var nodeDir = path.join(gyp.devDir, release.versionDir) + var modulesVersion = configure.test.nodeModulesVersion(nodeDir) + t.equal(modulesVersion, process.versions.modules, + nodeDir + ' modulesVersion=' + modulesVersion) +}) + +test('node modules version for installed targets', function (t) { + gyp.commands.list([], function(err, versions) { + if (err) return t.fail(err) + t.plan(versions.length) + + versions.forEach(function(version) { + var nodeDir = path.join(gyp.devDir, version) + var modulesVersion = configure.test.nodeModulesVersion(nodeDir) + t.ok(modulesVersion > 0, + nodeDir + ' modulesVersion=' + modulesVersion) + }) + }) +})