123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- 'use strict'
-
- const fs = require('graceful-fs')
- const log = require('npmlog')
- const path = require('path')
-
- function parseConfigGypi (config) {
- // translated from tools/js2c.py of Node.js
- // 1. string comments
- config = config.replace(/#.*/g, '')
- // 2. join multiline strings
- config = config.replace(/'$\s+'/mg, '')
- // 3. normalize string literals from ' into "
- config = config.replace(/'/g, '"')
- return JSON.parse(config)
- }
-
- async function getBaseConfigGypi ({ gyp, nodeDir }) {
- // try reading $nodeDir/include/node/config.gypi first when:
- // 1. --dist-url or --nodedir is specified
- // 2. and --force-process-config is not specified
- const useCustomHeaders = gyp.opts.nodedir || gyp.opts.disturl || gyp.opts['dist-url']
- const shouldReadConfigGypi = useCustomHeaders && !gyp.opts['force-process-config']
- if (shouldReadConfigGypi && nodeDir) {
- try {
- const baseConfigGypiPath = path.resolve(nodeDir, 'include/node/config.gypi')
- const baseConfigGypi = await fs.promises.readFile(baseConfigGypiPath)
- return parseConfigGypi(baseConfigGypi.toString())
- } catch (err) {
- log.warn('read config.gypi', err.message)
- }
- }
-
- // fallback to process.config if it is invalid
- return JSON.parse(JSON.stringify(process.config))
- }
-
- async function getCurrentConfigGypi ({ gyp, nodeDir, vsInfo }) {
- const config = await getBaseConfigGypi({ gyp, nodeDir })
- if (!config.target_defaults) {
- config.target_defaults = {}
- }
- if (!config.variables) {
- config.variables = {}
- }
-
- 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
- }
-
- async function createConfigGypi ({ gyp, buildDir, nodeDir, vsInfo }) {
- const configFilename = 'config.gypi'
- const configPath = path.resolve(buildDir, configFilename)
-
- log.verbose('build/' + configFilename, 'creating config file')
-
- const config = await 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)
- await fs.promises.writeFile(configPath, [prefix, json, ''].join('\n'))
-
- return configPath
- }
-
- module.exports = createConfigGypi
- module.exports.test = {
- parseConfigGypi: parseConfigGypi,
- getCurrentConfigGypi: getCurrentConfigGypi
- }
|