Skip to content

Commit

Permalink
chore: refactor the creation of config.gypi file
Browse files Browse the repository at this point in the history
  • Loading branch information
zcbenz authored and rvagg committed Sep 10, 2021
1 parent bc47cd6 commit f2ad87f
Show file tree
Hide file tree
Showing 4 changed files with 162 additions and 97 deletions.
1 change: 1 addition & 0 deletions .gitignore
@@ -1,3 +1,4 @@
*.swp
gyp/test
node_modules
test/.node-gyp
Expand Down
102 changes: 5 additions & 97 deletions lib/configure.js
Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Expand Down
119 changes: 119 additions & 0 deletions 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
}
37 changes: 37 additions & 0 deletions 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)
})

0 comments on commit f2ad87f

Please sign in to comment.