From f2ad87ff65f98ad66daa7225ad59d99b759a2b07 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 6 Sep 2021 11:18:24 +0900 Subject: [PATCH] chore: refactor the creation of config.gypi file --- .gitignore | 1 + lib/configure.js | 102 ++------------------------- lib/create-config-gypi.js | 119 ++++++++++++++++++++++++++++++++ test/test-create-config-gypi.js | 37 ++++++++++ 4 files changed, 162 insertions(+), 97 deletions(-) create mode 100644 lib/create-config-gypi.js create mode 100644 test/test-create-config-gypi.js diff --git a/.gitignore b/.gitignore index 776066e34d..e906ca7280 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +*.swp gyp/test node_modules test/.node-gyp diff --git a/lib/configure.js b/lib/configure.js index 038ccbf20f..682f1e6f95 100644 --- a/lib/configure.js +++ b/lib/configure.js @@ -7,6 +7,7 @@ const os = require('os') const processRelease = require('./process-release') const win = process.platform === 'win32' const findNodeDirectory = require('./find-node-directory') +const createConfigGypi = require('./create-config-gypi') const msgFormat = require('util').format var findPython = require('./find-python') if (win) { @@ -92,107 +93,14 @@ function configure (gyp, argv, callback) { if (err) { return callback(err) } - - var configFilename = 'config.gypi' - var configPath = path.resolve(buildDir, configFilename) - - log.verbose('build/' + configFilename, 'creating config file') - - var config = process.config ? JSON.parse(JSON.stringify(process.config)) : {} - var defaults = config.target_defaults - var variables = config.variables - - // default "config.variables" - if (!variables) { - variables = config.variables = {} - } - - // default "config.defaults" - if (!defaults) { - defaults = config.target_defaults = {} - } - - // don't inherit the "defaults" from node's `process.config` object. - // doing so could cause problems in cases where the `node` executable was - // compiled on a different machine (with different lib/include paths) than - // the machine where the addon is being built to - defaults.cflags = [] - defaults.defines = [] - defaults.include_dirs = [] - defaults.libraries = [] - - // set the default_configuration prop - if ('debug' in gyp.opts) { - defaults.default_configuration = gyp.opts.debug ? 'Debug' : 'Release' - } - - if (!defaults.default_configuration) { - defaults.default_configuration = 'Release' - } - - // set the target_arch variable - variables.target_arch = gyp.opts.arch || process.arch || 'ia32' - if (variables.target_arch === 'arm64') { - defaults.msvs_configuration_platform = 'ARM64' - defaults.xcode_configuration_platform = 'arm64' - } - - // set the node development directory - variables.nodedir = nodeDir - - // disable -T "thin" static archives by default - variables.standalone_static_library = gyp.opts.thin ? 0 : 1 - - if (win) { + if (process.platform === 'win32') { 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 (variables.target_arch === 'arm64') { - if (vsInfo.versionMajor > 15 || - (vsInfo.versionMajor === 15 && vsInfo.versionMajor >= 9)) { - defaults.msvs_enable_marmasm = 1 - } else { - log.warn('Compiling ARM64 assembly is only available in\n' + - 'Visual Studio 2017 version 15.9 and above') - } - } - variables.msbuild_path = vsInfo.msBuild } - - // loop through the rest of the opts and add the unknown ones as variables. - // this allows for module-specific configure flags like: - // - // $ node-gyp configure --shared-libxml2 - Object.keys(gyp.opts).forEach(function (opt) { - if (opt === 'argv') { - return - } - if (opt in gyp.configDefs) { - return - } - variables[opt.replace(/-/g, '_')] = gyp.opts[opt] + createConfigGypi({ gyp, buildDir, nodeDir, vsInfo }, (err, configPath) => { + configs.push(configPath) + findConfigs(err) }) - - // ensures that any boolean values from `process.config` get stringified - function boolsToString (k, v) { - if (typeof v === 'boolean') { - return String(v) - } - return v - } - - log.silly('build/' + configFilename, config) - - // now write out the config.gypi file to the build/ dir - var prefix = '# Do not edit. File was generated by node-gyp\'s "configure" step' - - var json = JSON.stringify(config, boolsToString, 2) - log.verbose('build/' + configFilename, 'writing out config file: %s', configPath) - configs.push(configPath) - fs.writeFile(configPath, [prefix, json, ''].join('\n'), findConfigs) } function findConfigs (err) { diff --git a/lib/create-config-gypi.js b/lib/create-config-gypi.js new file mode 100644 index 0000000000..4d137e6b59 --- /dev/null +++ b/lib/create-config-gypi.js @@ -0,0 +1,119 @@ +'use strict' + +const fs = require('graceful-fs') +const log = require('npmlog') +const path = require('path') + +function getBaseConfigGypi () { + const config = JSON.parse(JSON.stringify(process.config)) + if (!config.target_defaults) { + config.target_defaults = {} + } + if (!config.variables) { + config.variables = {} + } + return config +} + +function getCurrentConfigGypi ({ gyp, nodeDir, vsInfo }) { + const config = getBaseConfigGypi() + const defaults = config.target_defaults + const variables = config.variables + + // don't inherit the "defaults" from the base config.gypi. + // doing so could cause problems in cases where the `node` executable was + // compiled on a different machine (with different lib/include paths) than + // the machine where the addon is being built to + defaults.cflags = [] + defaults.defines = [] + defaults.include_dirs = [] + defaults.libraries = [] + + // set the default_configuration prop + if ('debug' in gyp.opts) { + defaults.default_configuration = gyp.opts.debug ? 'Debug' : 'Release' + } + + if (!defaults.default_configuration) { + defaults.default_configuration = 'Release' + } + + // set the target_arch variable + variables.target_arch = gyp.opts.arch || process.arch || 'ia32' + if (variables.target_arch === 'arm64') { + defaults.msvs_configuration_platform = 'ARM64' + defaults.xcode_configuration_platform = 'arm64' + } + + // set the node development directory + variables.nodedir = nodeDir + + // disable -T "thin" static archives by default + variables.standalone_static_library = gyp.opts.thin ? 0 : 1 + + if (process.platform === 'win32') { + defaults.msbuild_toolset = vsInfo.toolset + if (vsInfo.sdk) { + defaults.msvs_windows_target_platform_version = vsInfo.sdk + } + if (variables.target_arch === 'arm64') { + if (vsInfo.versionMajor > 15 || + (vsInfo.versionMajor === 15 && vsInfo.versionMajor >= 9)) { + defaults.msvs_enable_marmasm = 1 + } else { + log.warn('Compiling ARM64 assembly is only available in\n' + + 'Visual Studio 2017 version 15.9 and above') + } + } + variables.msbuild_path = vsInfo.msBuild + } + + // loop through the rest of the opts and add the unknown ones as variables. + // this allows for module-specific configure flags like: + // + // $ node-gyp configure --shared-libxml2 + Object.keys(gyp.opts).forEach(function (opt) { + if (opt === 'argv') { + return + } + if (opt in gyp.configDefs) { + return + } + variables[opt.replace(/-/g, '_')] = gyp.opts[opt] + }) + + return config +} + +function createConfigGypi ({ gyp, buildDir, nodeDir, vsInfo }, callback) { + const configFilename = 'config.gypi' + const configPath = path.resolve(buildDir, configFilename) + + log.verbose('build/' + configFilename, 'creating config file') + + const config = getCurrentConfigGypi({ gyp, nodeDir, vsInfo }) + + // ensures that any boolean values in config.gypi get stringified + function boolsToString (k, v) { + if (typeof v === 'boolean') { + return String(v) + } + return v + } + + log.silly('build/' + configFilename, config) + + // now write out the config.gypi file to the build/ dir + const prefix = '# Do not edit. File was generated by node-gyp\'s "configure" step' + + const json = JSON.stringify(config, boolsToString, 2) + log.verbose('build/' + configFilename, 'writing out config file: %s', configPath) + fs.writeFile(configPath, [prefix, json, ''].join('\n'), (err) => { + callback(err, configPath) + }) +} + +module.exports = createConfigGypi +module.exports.test = { + getCurrentConfigGypi: getCurrentConfigGypi +} diff --git a/test/test-create-config-gypi.js b/test/test-create-config-gypi.js new file mode 100644 index 0000000000..933cae1326 --- /dev/null +++ b/test/test-create-config-gypi.js @@ -0,0 +1,37 @@ +'use strict' + +const { test } = require('tap') +const gyp = require('../lib/node-gyp') +const createConfigGypi = require('../lib/create-config-gypi') +const { getCurrentConfigGypi } = createConfigGypi.test + +test('config.gypi with no options', function (t) { + t.plan(2) + + const prog = gyp() + prog.parseArgv([]) + + const config = getCurrentConfigGypi({ gyp: prog, vsInfo: {} }) + t.equal(config.target_defaults.default_configuration, 'Release') + t.equal(config.variables.target_arch, process.arch) +}) + +test('config.gypi with --debug', function (t) { + t.plan(1) + + const prog = gyp() + prog.parseArgv(['_', '_', '--debug']) + + const config = getCurrentConfigGypi({ gyp: prog, vsInfo: {} }) + t.equal(config.target_defaults.default_configuration, 'Debug') +}) + +test('config.gypi with custom options', function (t) { + t.plan(1) + + const prog = gyp() + prog.parseArgv(['_', '_', '--shared-libxml2']) + + const config = getCurrentConfigGypi({ gyp: prog, vsInfo: {} }) + t.equal(config.variables.shared_libxml2, true) +})