11cb0ef41Sopenharmony_ci'use strict' 21cb0ef41Sopenharmony_ci 31cb0ef41Sopenharmony_ciconst { promises: fs } = require('graceful-fs') 41cb0ef41Sopenharmony_ciconst path = require('path') 51cb0ef41Sopenharmony_ciconst log = require('./log') 61cb0ef41Sopenharmony_ciconst os = require('os') 71cb0ef41Sopenharmony_ciconst processRelease = require('./process-release') 81cb0ef41Sopenharmony_ciconst win = process.platform === 'win32' 91cb0ef41Sopenharmony_ciconst findNodeDirectory = require('./find-node-directory') 101cb0ef41Sopenharmony_ciconst { createConfigGypi } = require('./create-config-gypi') 111cb0ef41Sopenharmony_ciconst { format: msgFormat } = require('util') 121cb0ef41Sopenharmony_ciconst { findAccessibleSync } = require('./util') 131cb0ef41Sopenharmony_ciconst { findPython } = require('./find-python') 141cb0ef41Sopenharmony_ciconst { findVisualStudio } = win ? require('./find-visualstudio') : {} 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_ciasync function configure (gyp, argv) { 171cb0ef41Sopenharmony_ci const buildDir = path.resolve('build') 181cb0ef41Sopenharmony_ci const configNames = ['config.gypi', 'common.gypi'] 191cb0ef41Sopenharmony_ci const configs = [] 201cb0ef41Sopenharmony_ci let nodeDir 211cb0ef41Sopenharmony_ci const release = processRelease(argv, gyp, process.version, process.release) 221cb0ef41Sopenharmony_ci 231cb0ef41Sopenharmony_ci const python = await findPython(gyp.opts.python) 241cb0ef41Sopenharmony_ci return getNodeDir() 251cb0ef41Sopenharmony_ci 261cb0ef41Sopenharmony_ci async function getNodeDir () { 271cb0ef41Sopenharmony_ci // 'python' should be set by now 281cb0ef41Sopenharmony_ci process.env.PYTHON = python 291cb0ef41Sopenharmony_ci 301cb0ef41Sopenharmony_ci if (gyp.opts.nodedir) { 311cb0ef41Sopenharmony_ci // --nodedir was specified. use that for the dev files 321cb0ef41Sopenharmony_ci nodeDir = gyp.opts.nodedir.replace(/^~/, os.homedir()) 331cb0ef41Sopenharmony_ci log.verbose('get node dir', 'compiling against specified --nodedir dev files: %s', nodeDir) 341cb0ef41Sopenharmony_ci } else { 351cb0ef41Sopenharmony_ci // if no --nodedir specified, ensure node dependencies are installed 361cb0ef41Sopenharmony_ci if ('v' + release.version !== process.version) { 371cb0ef41Sopenharmony_ci // if --target was given, then determine a target version to compile for 381cb0ef41Sopenharmony_ci log.verbose('get node dir', 'compiling against --target node version: %s', release.version) 391cb0ef41Sopenharmony_ci } else { 401cb0ef41Sopenharmony_ci // if no --target was specified then use the current host node version 411cb0ef41Sopenharmony_ci log.verbose('get node dir', 'no --target version specified, falling back to host node version: %s', release.version) 421cb0ef41Sopenharmony_ci } 431cb0ef41Sopenharmony_ci 441cb0ef41Sopenharmony_ci if (!release.semver) { 451cb0ef41Sopenharmony_ci // could not parse the version string with semver 461cb0ef41Sopenharmony_ci throw new Error('Invalid version number: ' + release.version) 471cb0ef41Sopenharmony_ci } 481cb0ef41Sopenharmony_ci 491cb0ef41Sopenharmony_ci // If the tarball option is set, always remove and reinstall the headers 501cb0ef41Sopenharmony_ci // into devdir. Otherwise only install if they're not already there. 511cb0ef41Sopenharmony_ci gyp.opts.ensure = !gyp.opts.tarball 521cb0ef41Sopenharmony_ci 531cb0ef41Sopenharmony_ci await gyp.commands.install([release.version]) 541cb0ef41Sopenharmony_ci 551cb0ef41Sopenharmony_ci log.verbose('get node dir', 'target node version installed:', release.versionDir) 561cb0ef41Sopenharmony_ci nodeDir = path.resolve(gyp.devDir, release.versionDir) 571cb0ef41Sopenharmony_ci } 581cb0ef41Sopenharmony_ci 591cb0ef41Sopenharmony_ci return createBuildDir() 601cb0ef41Sopenharmony_ci } 611cb0ef41Sopenharmony_ci 621cb0ef41Sopenharmony_ci async function createBuildDir () { 631cb0ef41Sopenharmony_ci log.verbose('build dir', 'attempting to create "build" dir: %s', buildDir) 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_ci const isNew = await fs.mkdir(buildDir, { recursive: true }) 661cb0ef41Sopenharmony_ci log.verbose( 671cb0ef41Sopenharmony_ci 'build dir', '"build" dir needed to be created?', isNew ? 'Yes' : 'No' 681cb0ef41Sopenharmony_ci ) 691cb0ef41Sopenharmony_ci const vsInfo = win ? await findVisualStudio(release.semver, gyp.opts['msvs-version']) : null 701cb0ef41Sopenharmony_ci return createConfigFile(vsInfo) 711cb0ef41Sopenharmony_ci } 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_ci async function createConfigFile (vsInfo) { 741cb0ef41Sopenharmony_ci if (win) { 751cb0ef41Sopenharmony_ci process.env.GYP_MSVS_VERSION = Math.min(vsInfo.versionYear, 2015) 761cb0ef41Sopenharmony_ci process.env.GYP_MSVS_OVERRIDE_PATH = vsInfo.path 771cb0ef41Sopenharmony_ci } 781cb0ef41Sopenharmony_ci const configPath = await createConfigGypi({ gyp, buildDir, nodeDir, vsInfo, python }) 791cb0ef41Sopenharmony_ci configs.push(configPath) 801cb0ef41Sopenharmony_ci return findConfigs() 811cb0ef41Sopenharmony_ci } 821cb0ef41Sopenharmony_ci 831cb0ef41Sopenharmony_ci async function findConfigs () { 841cb0ef41Sopenharmony_ci const name = configNames.shift() 851cb0ef41Sopenharmony_ci if (!name) { 861cb0ef41Sopenharmony_ci return runGyp() 871cb0ef41Sopenharmony_ci } 881cb0ef41Sopenharmony_ci 891cb0ef41Sopenharmony_ci const fullPath = path.resolve(name) 901cb0ef41Sopenharmony_ci log.verbose(name, 'checking for gypi file: %s', fullPath) 911cb0ef41Sopenharmony_ci try { 921cb0ef41Sopenharmony_ci await fs.stat(fullPath) 931cb0ef41Sopenharmony_ci log.verbose(name, 'found gypi file') 941cb0ef41Sopenharmony_ci configs.push(fullPath) 951cb0ef41Sopenharmony_ci } catch (err) { 961cb0ef41Sopenharmony_ci // ENOENT will check next gypi filename 971cb0ef41Sopenharmony_ci if (err.code !== 'ENOENT') { 981cb0ef41Sopenharmony_ci throw err 991cb0ef41Sopenharmony_ci } 1001cb0ef41Sopenharmony_ci } 1011cb0ef41Sopenharmony_ci 1021cb0ef41Sopenharmony_ci return findConfigs() 1031cb0ef41Sopenharmony_ci } 1041cb0ef41Sopenharmony_ci 1051cb0ef41Sopenharmony_ci async function runGyp () { 1061cb0ef41Sopenharmony_ci if (!~argv.indexOf('-f') && !~argv.indexOf('--format')) { 1071cb0ef41Sopenharmony_ci if (win) { 1081cb0ef41Sopenharmony_ci log.verbose('gyp', 'gyp format was not specified; forcing "msvs"') 1091cb0ef41Sopenharmony_ci // force the 'make' target for non-Windows 1101cb0ef41Sopenharmony_ci argv.push('-f', 'msvs') 1111cb0ef41Sopenharmony_ci } else { 1121cb0ef41Sopenharmony_ci log.verbose('gyp', 'gyp format was not specified; forcing "make"') 1131cb0ef41Sopenharmony_ci // force the 'make' target for non-Windows 1141cb0ef41Sopenharmony_ci argv.push('-f', 'make') 1151cb0ef41Sopenharmony_ci } 1161cb0ef41Sopenharmony_ci } 1171cb0ef41Sopenharmony_ci 1181cb0ef41Sopenharmony_ci // include all the ".gypi" files that were found 1191cb0ef41Sopenharmony_ci configs.forEach(function (config) { 1201cb0ef41Sopenharmony_ci argv.push('-I', config) 1211cb0ef41Sopenharmony_ci }) 1221cb0ef41Sopenharmony_ci 1231cb0ef41Sopenharmony_ci // For AIX and z/OS we need to set up the path to the exports file 1241cb0ef41Sopenharmony_ci // which contains the symbols needed for linking. 1251cb0ef41Sopenharmony_ci let nodeExpFile 1261cb0ef41Sopenharmony_ci let nodeRootDir 1271cb0ef41Sopenharmony_ci let candidates 1281cb0ef41Sopenharmony_ci let logprefix = 'find exports file' 1291cb0ef41Sopenharmony_ci if (process.platform === 'aix' || process.platform === 'os390' || process.platform === 'os400') { 1301cb0ef41Sopenharmony_ci const ext = process.platform === 'os390' ? 'x' : 'exp' 1311cb0ef41Sopenharmony_ci nodeRootDir = findNodeDirectory() 1321cb0ef41Sopenharmony_ci 1331cb0ef41Sopenharmony_ci if (process.platform === 'aix' || process.platform === 'os400') { 1341cb0ef41Sopenharmony_ci candidates = [ 1351cb0ef41Sopenharmony_ci 'include/node/node', 1361cb0ef41Sopenharmony_ci 'out/Release/node', 1371cb0ef41Sopenharmony_ci 'out/Debug/node', 1381cb0ef41Sopenharmony_ci 'node' 1391cb0ef41Sopenharmony_ci ].map(function (file) { 1401cb0ef41Sopenharmony_ci return file + '.' + ext 1411cb0ef41Sopenharmony_ci }) 1421cb0ef41Sopenharmony_ci } else { 1431cb0ef41Sopenharmony_ci candidates = [ 1441cb0ef41Sopenharmony_ci 'out/Release/lib.target/libnode', 1451cb0ef41Sopenharmony_ci 'out/Debug/lib.target/libnode', 1461cb0ef41Sopenharmony_ci 'out/Release/obj.target/libnode', 1471cb0ef41Sopenharmony_ci 'out/Debug/obj.target/libnode', 1481cb0ef41Sopenharmony_ci 'lib/libnode' 1491cb0ef41Sopenharmony_ci ].map(function (file) { 1501cb0ef41Sopenharmony_ci return file + '.' + ext 1511cb0ef41Sopenharmony_ci }) 1521cb0ef41Sopenharmony_ci } 1531cb0ef41Sopenharmony_ci 1541cb0ef41Sopenharmony_ci nodeExpFile = findAccessibleSync(logprefix, nodeRootDir, candidates) 1551cb0ef41Sopenharmony_ci if (nodeExpFile !== undefined) { 1561cb0ef41Sopenharmony_ci log.verbose(logprefix, 'Found exports file: %s', nodeExpFile) 1571cb0ef41Sopenharmony_ci } else { 1581cb0ef41Sopenharmony_ci const msg = msgFormat('Could not find node.%s file in %s', ext, nodeRootDir) 1591cb0ef41Sopenharmony_ci log.error(logprefix, 'Could not find exports file') 1601cb0ef41Sopenharmony_ci throw new Error(msg) 1611cb0ef41Sopenharmony_ci } 1621cb0ef41Sopenharmony_ci } 1631cb0ef41Sopenharmony_ci 1641cb0ef41Sopenharmony_ci // For z/OS we need to set up the path to zoslib include directory, 1651cb0ef41Sopenharmony_ci // which contains headers included in v8config.h. 1661cb0ef41Sopenharmony_ci let zoslibIncDir 1671cb0ef41Sopenharmony_ci if (process.platform === 'os390') { 1681cb0ef41Sopenharmony_ci logprefix = "find zoslib's zos-base.h:" 1691cb0ef41Sopenharmony_ci let msg 1701cb0ef41Sopenharmony_ci let zoslibIncPath = process.env.ZOSLIB_INCLUDES 1711cb0ef41Sopenharmony_ci if (zoslibIncPath) { 1721cb0ef41Sopenharmony_ci zoslibIncPath = findAccessibleSync(logprefix, zoslibIncPath, ['zos-base.h']) 1731cb0ef41Sopenharmony_ci if (zoslibIncPath === undefined) { 1741cb0ef41Sopenharmony_ci msg = msgFormat('Could not find zos-base.h file in the directory set ' + 1751cb0ef41Sopenharmony_ci 'in ZOSLIB_INCLUDES environment variable: %s; set it ' + 1761cb0ef41Sopenharmony_ci 'to the correct path, or unset it to search %s', process.env.ZOSLIB_INCLUDES, nodeRootDir) 1771cb0ef41Sopenharmony_ci } 1781cb0ef41Sopenharmony_ci } else { 1791cb0ef41Sopenharmony_ci candidates = [ 1801cb0ef41Sopenharmony_ci 'include/node/zoslib/zos-base.h', 1811cb0ef41Sopenharmony_ci 'include/zoslib/zos-base.h', 1821cb0ef41Sopenharmony_ci 'zoslib/include/zos-base.h', 1831cb0ef41Sopenharmony_ci 'install/include/node/zoslib/zos-base.h' 1841cb0ef41Sopenharmony_ci ] 1851cb0ef41Sopenharmony_ci zoslibIncPath = findAccessibleSync(logprefix, nodeRootDir, candidates) 1861cb0ef41Sopenharmony_ci if (zoslibIncPath === undefined) { 1871cb0ef41Sopenharmony_ci msg = msgFormat('Could not find any of %s in directory %s; set ' + 1881cb0ef41Sopenharmony_ci 'environmant variable ZOSLIB_INCLUDES to the path ' + 1891cb0ef41Sopenharmony_ci 'that contains zos-base.h', candidates.toString(), nodeRootDir) 1901cb0ef41Sopenharmony_ci } 1911cb0ef41Sopenharmony_ci } 1921cb0ef41Sopenharmony_ci if (zoslibIncPath !== undefined) { 1931cb0ef41Sopenharmony_ci zoslibIncDir = path.dirname(zoslibIncPath) 1941cb0ef41Sopenharmony_ci log.verbose(logprefix, "Found zoslib's zos-base.h in: %s", zoslibIncDir) 1951cb0ef41Sopenharmony_ci } else if (release.version.split('.')[0] >= 16) { 1961cb0ef41Sopenharmony_ci // zoslib is only shipped in Node v16 and above. 1971cb0ef41Sopenharmony_ci log.error(logprefix, msg) 1981cb0ef41Sopenharmony_ci throw new Error(msg) 1991cb0ef41Sopenharmony_ci } 2001cb0ef41Sopenharmony_ci } 2011cb0ef41Sopenharmony_ci 2021cb0ef41Sopenharmony_ci // this logic ported from the old `gyp_addon` python file 2031cb0ef41Sopenharmony_ci const gypScript = path.resolve(__dirname, '..', 'gyp', 'gyp_main.py') 2041cb0ef41Sopenharmony_ci const addonGypi = path.resolve(__dirname, '..', 'addon.gypi') 2051cb0ef41Sopenharmony_ci let commonGypi = path.resolve(nodeDir, 'include/node/common.gypi') 2061cb0ef41Sopenharmony_ci try { 2071cb0ef41Sopenharmony_ci await fs.stat(commonGypi) 2081cb0ef41Sopenharmony_ci } catch (err) { 2091cb0ef41Sopenharmony_ci commonGypi = path.resolve(nodeDir, 'common.gypi') 2101cb0ef41Sopenharmony_ci } 2111cb0ef41Sopenharmony_ci 2121cb0ef41Sopenharmony_ci let outputDir = 'build' 2131cb0ef41Sopenharmony_ci if (win) { 2141cb0ef41Sopenharmony_ci // Windows expects an absolute path 2151cb0ef41Sopenharmony_ci outputDir = buildDir 2161cb0ef41Sopenharmony_ci } 2171cb0ef41Sopenharmony_ci const nodeGypDir = path.resolve(__dirname, '..') 2181cb0ef41Sopenharmony_ci 2191cb0ef41Sopenharmony_ci let nodeLibFile = path.join(nodeDir, 2201cb0ef41Sopenharmony_ci !gyp.opts.nodedir ? '<(target_arch)' : '$(Configuration)', 2211cb0ef41Sopenharmony_ci release.name + '.lib') 2221cb0ef41Sopenharmony_ci 2231cb0ef41Sopenharmony_ci argv.push('-I', addonGypi) 2241cb0ef41Sopenharmony_ci argv.push('-I', commonGypi) 2251cb0ef41Sopenharmony_ci argv.push('-Dlibrary=shared_library') 2261cb0ef41Sopenharmony_ci argv.push('-Dvisibility=default') 2271cb0ef41Sopenharmony_ci argv.push('-Dnode_root_dir=' + nodeDir) 2281cb0ef41Sopenharmony_ci if (process.platform === 'aix' || process.platform === 'os390' || process.platform === 'os400') { 2291cb0ef41Sopenharmony_ci argv.push('-Dnode_exp_file=' + nodeExpFile) 2301cb0ef41Sopenharmony_ci if (process.platform === 'os390' && zoslibIncDir) { 2311cb0ef41Sopenharmony_ci argv.push('-Dzoslib_include_dir=' + zoslibIncDir) 2321cb0ef41Sopenharmony_ci } 2331cb0ef41Sopenharmony_ci } 2341cb0ef41Sopenharmony_ci argv.push('-Dnode_gyp_dir=' + nodeGypDir) 2351cb0ef41Sopenharmony_ci 2361cb0ef41Sopenharmony_ci // Do this to keep Cygwin environments happy, else the unescaped '\' gets eaten up, 2371cb0ef41Sopenharmony_ci // resulting in bad paths, Ex c:parentFolderfolderanotherFolder instead of c:\parentFolder\folder\anotherFolder 2381cb0ef41Sopenharmony_ci if (win) { 2391cb0ef41Sopenharmony_ci nodeLibFile = nodeLibFile.replace(/\\/g, '\\\\') 2401cb0ef41Sopenharmony_ci } 2411cb0ef41Sopenharmony_ci argv.push('-Dnode_lib_file=' + nodeLibFile) 2421cb0ef41Sopenharmony_ci argv.push('-Dmodule_root_dir=' + process.cwd()) 2431cb0ef41Sopenharmony_ci argv.push('-Dnode_engine=' + 2441cb0ef41Sopenharmony_ci (gyp.opts.node_engine || process.jsEngine || 'v8')) 2451cb0ef41Sopenharmony_ci argv.push('--depth=.') 2461cb0ef41Sopenharmony_ci argv.push('--no-parallel') 2471cb0ef41Sopenharmony_ci 2481cb0ef41Sopenharmony_ci // tell gyp to write the Makefile/Solution files into output_dir 2491cb0ef41Sopenharmony_ci argv.push('--generator-output', outputDir) 2501cb0ef41Sopenharmony_ci 2511cb0ef41Sopenharmony_ci // tell make to write its output into the same dir 2521cb0ef41Sopenharmony_ci argv.push('-Goutput_dir=.') 2531cb0ef41Sopenharmony_ci 2541cb0ef41Sopenharmony_ci // enforce use of the "binding.gyp" file 2551cb0ef41Sopenharmony_ci argv.unshift('binding.gyp') 2561cb0ef41Sopenharmony_ci 2571cb0ef41Sopenharmony_ci // execute `gyp` from the current target nodedir 2581cb0ef41Sopenharmony_ci argv.unshift(gypScript) 2591cb0ef41Sopenharmony_ci 2601cb0ef41Sopenharmony_ci // make sure python uses files that came with this particular node package 2611cb0ef41Sopenharmony_ci const pypath = [path.join(__dirname, '..', 'gyp', 'pylib')] 2621cb0ef41Sopenharmony_ci if (process.env.PYTHONPATH) { 2631cb0ef41Sopenharmony_ci pypath.push(process.env.PYTHONPATH) 2641cb0ef41Sopenharmony_ci } 2651cb0ef41Sopenharmony_ci process.env.PYTHONPATH = pypath.join(win ? ';' : ':') 2661cb0ef41Sopenharmony_ci 2671cb0ef41Sopenharmony_ci await new Promise((resolve, reject) => { 2681cb0ef41Sopenharmony_ci const cp = gyp.spawn(python, argv) 2691cb0ef41Sopenharmony_ci cp.on('exit', (code) => { 2701cb0ef41Sopenharmony_ci if (code !== 0) { 2711cb0ef41Sopenharmony_ci reject(new Error('`gyp` failed with exit code: ' + code)) 2721cb0ef41Sopenharmony_ci } else { 2731cb0ef41Sopenharmony_ci // we're done 2741cb0ef41Sopenharmony_ci resolve() 2751cb0ef41Sopenharmony_ci } 2761cb0ef41Sopenharmony_ci }) 2771cb0ef41Sopenharmony_ci }) 2781cb0ef41Sopenharmony_ci } 2791cb0ef41Sopenharmony_ci} 2801cb0ef41Sopenharmony_ci 2811cb0ef41Sopenharmony_cimodule.exports = configure 2821cb0ef41Sopenharmony_cimodule.exports.usage = 'Generates ' + (win ? 'MSVC project files' : 'a Makefile') + ' for the current module' 283