| [81bc7da] | 1 | 'use strict'
|
|---|
| 2 |
|
|---|
| 3 | const fs = require('graceful-fs')
|
|---|
| 4 | const log = require('npmlog')
|
|---|
| 5 | const path = require('path')
|
|---|
| 6 |
|
|---|
| 7 | function parseConfigGypi (config) {
|
|---|
| 8 | // translated from tools/js2c.py of Node.js
|
|---|
| 9 | // 1. string comments
|
|---|
| 10 | config = config.replace(/#.*/g, '')
|
|---|
| 11 | // 2. join multiline strings
|
|---|
| 12 | config = config.replace(/'$\s+'/mg, '')
|
|---|
| 13 | // 3. normalize string literals from ' into "
|
|---|
| 14 | config = config.replace(/'/g, '"')
|
|---|
| 15 | return JSON.parse(config)
|
|---|
| 16 | }
|
|---|
| 17 |
|
|---|
| 18 | async function getBaseConfigGypi ({ gyp, nodeDir }) {
|
|---|
| 19 | // try reading $nodeDir/include/node/config.gypi first when:
|
|---|
| 20 | // 1. --dist-url or --nodedir is specified
|
|---|
| 21 | // 2. and --force-process-config is not specified
|
|---|
| 22 | const shouldReadConfigGypi = (gyp.opts.nodedir || gyp.opts['dist-url']) && !gyp.opts['force-process-config']
|
|---|
| 23 | if (shouldReadConfigGypi && nodeDir) {
|
|---|
| 24 | try {
|
|---|
| 25 | const baseConfigGypiPath = path.resolve(nodeDir, 'include/node/config.gypi')
|
|---|
| 26 | const baseConfigGypi = await fs.promises.readFile(baseConfigGypiPath)
|
|---|
| 27 | return parseConfigGypi(baseConfigGypi.toString())
|
|---|
| 28 | } catch (err) {
|
|---|
| 29 | log.warn('read config.gypi', err.message)
|
|---|
| 30 | }
|
|---|
| 31 | }
|
|---|
| 32 |
|
|---|
| 33 | // fallback to process.config if it is invalid
|
|---|
| 34 | return JSON.parse(JSON.stringify(process.config))
|
|---|
| 35 | }
|
|---|
| 36 |
|
|---|
| 37 | async function getCurrentConfigGypi ({ gyp, nodeDir, vsInfo }) {
|
|---|
| 38 | const config = await getBaseConfigGypi({ gyp, nodeDir })
|
|---|
| 39 | if (!config.target_defaults) {
|
|---|
| 40 | config.target_defaults = {}
|
|---|
| 41 | }
|
|---|
| 42 | if (!config.variables) {
|
|---|
| 43 | config.variables = {}
|
|---|
| 44 | }
|
|---|
| 45 |
|
|---|
| 46 | const defaults = config.target_defaults
|
|---|
| 47 | const variables = config.variables
|
|---|
| 48 |
|
|---|
| 49 | // don't inherit the "defaults" from the base config.gypi.
|
|---|
| 50 | // doing so could cause problems in cases where the `node` executable was
|
|---|
| 51 | // compiled on a different machine (with different lib/include paths) than
|
|---|
| 52 | // the machine where the addon is being built to
|
|---|
| 53 | defaults.cflags = []
|
|---|
| 54 | defaults.defines = []
|
|---|
| 55 | defaults.include_dirs = []
|
|---|
| 56 | defaults.libraries = []
|
|---|
| 57 |
|
|---|
| 58 | // set the default_configuration prop
|
|---|
| 59 | if ('debug' in gyp.opts) {
|
|---|
| 60 | defaults.default_configuration = gyp.opts.debug ? 'Debug' : 'Release'
|
|---|
| 61 | }
|
|---|
| 62 |
|
|---|
| 63 | if (!defaults.default_configuration) {
|
|---|
| 64 | defaults.default_configuration = 'Release'
|
|---|
| 65 | }
|
|---|
| 66 |
|
|---|
| 67 | // set the target_arch variable
|
|---|
| 68 | variables.target_arch = gyp.opts.arch || process.arch || 'ia32'
|
|---|
| 69 | if (variables.target_arch === 'arm64') {
|
|---|
| 70 | defaults.msvs_configuration_platform = 'ARM64'
|
|---|
| 71 | defaults.xcode_configuration_platform = 'arm64'
|
|---|
| 72 | }
|
|---|
| 73 |
|
|---|
| 74 | // set the node development directory
|
|---|
| 75 | variables.nodedir = nodeDir
|
|---|
| 76 |
|
|---|
| 77 | // disable -T "thin" static archives by default
|
|---|
| 78 | variables.standalone_static_library = gyp.opts.thin ? 0 : 1
|
|---|
| 79 |
|
|---|
| 80 | if (process.platform === 'win32') {
|
|---|
| 81 | defaults.msbuild_toolset = vsInfo.toolset
|
|---|
| 82 | if (vsInfo.sdk) {
|
|---|
| 83 | defaults.msvs_windows_target_platform_version = vsInfo.sdk
|
|---|
| 84 | }
|
|---|
| 85 | if (variables.target_arch === 'arm64') {
|
|---|
| 86 | if (vsInfo.versionMajor > 15 ||
|
|---|
| 87 | (vsInfo.versionMajor === 15 && vsInfo.versionMajor >= 9)) {
|
|---|
| 88 | defaults.msvs_enable_marmasm = 1
|
|---|
| 89 | } else {
|
|---|
| 90 | log.warn('Compiling ARM64 assembly is only available in\n' +
|
|---|
| 91 | 'Visual Studio 2017 version 15.9 and above')
|
|---|
| 92 | }
|
|---|
| 93 | }
|
|---|
| 94 | variables.msbuild_path = vsInfo.msBuild
|
|---|
| 95 | }
|
|---|
| 96 |
|
|---|
| 97 | // loop through the rest of the opts and add the unknown ones as variables.
|
|---|
| 98 | // this allows for module-specific configure flags like:
|
|---|
| 99 | //
|
|---|
| 100 | // $ node-gyp configure --shared-libxml2
|
|---|
| 101 | Object.keys(gyp.opts).forEach(function (opt) {
|
|---|
| 102 | if (opt === 'argv') {
|
|---|
| 103 | return
|
|---|
| 104 | }
|
|---|
| 105 | if (opt in gyp.configDefs) {
|
|---|
| 106 | return
|
|---|
| 107 | }
|
|---|
| 108 | variables[opt.replace(/-/g, '_')] = gyp.opts[opt]
|
|---|
| 109 | })
|
|---|
| 110 |
|
|---|
| 111 | return config
|
|---|
| 112 | }
|
|---|
| 113 |
|
|---|
| 114 | async function createConfigGypi ({ gyp, buildDir, nodeDir, vsInfo }) {
|
|---|
| 115 | const configFilename = 'config.gypi'
|
|---|
| 116 | const configPath = path.resolve(buildDir, configFilename)
|
|---|
| 117 |
|
|---|
| 118 | log.verbose('build/' + configFilename, 'creating config file')
|
|---|
| 119 |
|
|---|
| 120 | const config = await getCurrentConfigGypi({ gyp, nodeDir, vsInfo })
|
|---|
| 121 |
|
|---|
| 122 | // ensures that any boolean values in config.gypi get stringified
|
|---|
| 123 | function boolsToString (k, v) {
|
|---|
| 124 | if (typeof v === 'boolean') {
|
|---|
| 125 | return String(v)
|
|---|
| 126 | }
|
|---|
| 127 | return v
|
|---|
| 128 | }
|
|---|
| 129 |
|
|---|
| 130 | log.silly('build/' + configFilename, config)
|
|---|
| 131 |
|
|---|
| 132 | // now write out the config.gypi file to the build/ dir
|
|---|
| 133 | const prefix = '# Do not edit. File was generated by node-gyp\'s "configure" step'
|
|---|
| 134 |
|
|---|
| 135 | const json = JSON.stringify(config, boolsToString, 2)
|
|---|
| 136 | log.verbose('build/' + configFilename, 'writing out config file: %s', configPath)
|
|---|
| 137 | await fs.promises.writeFile(configPath, [prefix, json, ''].join('\n'))
|
|---|
| 138 |
|
|---|
| 139 | return configPath
|
|---|
| 140 | }
|
|---|
| 141 |
|
|---|
| 142 | module.exports = createConfigGypi
|
|---|
| 143 | module.exports.test = {
|
|---|
| 144 | parseConfigGypi: parseConfigGypi,
|
|---|
| 145 | getCurrentConfigGypi: getCurrentConfigGypi
|
|---|
| 146 | }
|
|---|