11cb0ef41Sopenharmony_ci'use strict' 21cb0ef41Sopenharmony_ci 31cb0ef41Sopenharmony_ciconst fs = require('graceful-fs').promises 41cb0ef41Sopenharmony_ciconst path = require('path') 51cb0ef41Sopenharmony_ciconst { glob } = require('glob') 61cb0ef41Sopenharmony_ciconst log = require('./log') 71cb0ef41Sopenharmony_ciconst which = require('which') 81cb0ef41Sopenharmony_ciconst win = process.platform === 'win32' 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_ciasync function build (gyp, argv) { 111cb0ef41Sopenharmony_ci let platformMake = 'make' 121cb0ef41Sopenharmony_ci if (process.platform === 'aix') { 131cb0ef41Sopenharmony_ci platformMake = 'gmake' 141cb0ef41Sopenharmony_ci } else if (process.platform === 'os400') { 151cb0ef41Sopenharmony_ci platformMake = 'gmake' 161cb0ef41Sopenharmony_ci } else if (process.platform.indexOf('bsd') !== -1) { 171cb0ef41Sopenharmony_ci platformMake = 'gmake' 181cb0ef41Sopenharmony_ci } else if (win && argv.length > 0) { 191cb0ef41Sopenharmony_ci argv = argv.map(function (target) { 201cb0ef41Sopenharmony_ci return '/t:' + target 211cb0ef41Sopenharmony_ci }) 221cb0ef41Sopenharmony_ci } 231cb0ef41Sopenharmony_ci 241cb0ef41Sopenharmony_ci const makeCommand = gyp.opts.make || process.env.MAKE || platformMake 251cb0ef41Sopenharmony_ci let command = win ? 'msbuild' : makeCommand 261cb0ef41Sopenharmony_ci const jobs = gyp.opts.jobs || process.env.JOBS 271cb0ef41Sopenharmony_ci let buildType 281cb0ef41Sopenharmony_ci let config 291cb0ef41Sopenharmony_ci let arch 301cb0ef41Sopenharmony_ci let nodeDir 311cb0ef41Sopenharmony_ci let guessedSolution 321cb0ef41Sopenharmony_ci let python 331cb0ef41Sopenharmony_ci let buildBinsDir 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_ci await loadConfigGypi() 361cb0ef41Sopenharmony_ci 371cb0ef41Sopenharmony_ci /** 381cb0ef41Sopenharmony_ci * Load the "config.gypi" file that was generated during "configure". 391cb0ef41Sopenharmony_ci */ 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_ci async function loadConfigGypi () { 421cb0ef41Sopenharmony_ci let data 431cb0ef41Sopenharmony_ci try { 441cb0ef41Sopenharmony_ci const configPath = path.resolve('build', 'config.gypi') 451cb0ef41Sopenharmony_ci data = await fs.readFile(configPath, 'utf8') 461cb0ef41Sopenharmony_ci } catch (err) { 471cb0ef41Sopenharmony_ci if (err.code === 'ENOENT') { 481cb0ef41Sopenharmony_ci throw new Error('You must run `node-gyp configure` first!') 491cb0ef41Sopenharmony_ci } else { 501cb0ef41Sopenharmony_ci throw err 511cb0ef41Sopenharmony_ci } 521cb0ef41Sopenharmony_ci } 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_ci config = JSON.parse(data.replace(/#.+\n/, '')) 551cb0ef41Sopenharmony_ci 561cb0ef41Sopenharmony_ci // get the 'arch', 'buildType', and 'nodeDir' vars from the config 571cb0ef41Sopenharmony_ci buildType = config.target_defaults.default_configuration 581cb0ef41Sopenharmony_ci arch = config.variables.target_arch 591cb0ef41Sopenharmony_ci nodeDir = config.variables.nodedir 601cb0ef41Sopenharmony_ci python = config.variables.python 611cb0ef41Sopenharmony_ci 621cb0ef41Sopenharmony_ci if ('debug' in gyp.opts) { 631cb0ef41Sopenharmony_ci buildType = gyp.opts.debug ? 'Debug' : 'Release' 641cb0ef41Sopenharmony_ci } 651cb0ef41Sopenharmony_ci if (!buildType) { 661cb0ef41Sopenharmony_ci buildType = 'Release' 671cb0ef41Sopenharmony_ci } 681cb0ef41Sopenharmony_ci 691cb0ef41Sopenharmony_ci log.verbose('build type', buildType) 701cb0ef41Sopenharmony_ci log.verbose('architecture', arch) 711cb0ef41Sopenharmony_ci log.verbose('node dev dir', nodeDir) 721cb0ef41Sopenharmony_ci log.verbose('python', python) 731cb0ef41Sopenharmony_ci 741cb0ef41Sopenharmony_ci if (win) { 751cb0ef41Sopenharmony_ci await findSolutionFile() 761cb0ef41Sopenharmony_ci } else { 771cb0ef41Sopenharmony_ci await doWhich() 781cb0ef41Sopenharmony_ci } 791cb0ef41Sopenharmony_ci } 801cb0ef41Sopenharmony_ci 811cb0ef41Sopenharmony_ci /** 821cb0ef41Sopenharmony_ci * On Windows, find the first build/*.sln file. 831cb0ef41Sopenharmony_ci */ 841cb0ef41Sopenharmony_ci 851cb0ef41Sopenharmony_ci async function findSolutionFile () { 861cb0ef41Sopenharmony_ci const files = await glob('build/*.sln') 871cb0ef41Sopenharmony_ci if (files.length === 0) { 881cb0ef41Sopenharmony_ci throw new Error('Could not find *.sln file. Did you run "configure"?') 891cb0ef41Sopenharmony_ci } 901cb0ef41Sopenharmony_ci guessedSolution = files[0] 911cb0ef41Sopenharmony_ci log.verbose('found first Solution file', guessedSolution) 921cb0ef41Sopenharmony_ci await doWhich() 931cb0ef41Sopenharmony_ci } 941cb0ef41Sopenharmony_ci 951cb0ef41Sopenharmony_ci /** 961cb0ef41Sopenharmony_ci * Uses node-which to locate the msbuild / make executable. 971cb0ef41Sopenharmony_ci */ 981cb0ef41Sopenharmony_ci 991cb0ef41Sopenharmony_ci async function doWhich () { 1001cb0ef41Sopenharmony_ci // On Windows use msbuild provided by node-gyp configure 1011cb0ef41Sopenharmony_ci if (win) { 1021cb0ef41Sopenharmony_ci if (!config.variables.msbuild_path) { 1031cb0ef41Sopenharmony_ci throw new Error('MSBuild is not set, please run `node-gyp configure`.') 1041cb0ef41Sopenharmony_ci } 1051cb0ef41Sopenharmony_ci command = config.variables.msbuild_path 1061cb0ef41Sopenharmony_ci log.verbose('using MSBuild:', command) 1071cb0ef41Sopenharmony_ci await doBuild() 1081cb0ef41Sopenharmony_ci return 1091cb0ef41Sopenharmony_ci } 1101cb0ef41Sopenharmony_ci 1111cb0ef41Sopenharmony_ci // First make sure we have the build command in the PATH 1121cb0ef41Sopenharmony_ci const execPath = await which(command) 1131cb0ef41Sopenharmony_ci log.verbose('`which` succeeded for `' + command + '`', execPath) 1141cb0ef41Sopenharmony_ci await doBuild() 1151cb0ef41Sopenharmony_ci } 1161cb0ef41Sopenharmony_ci 1171cb0ef41Sopenharmony_ci /** 1181cb0ef41Sopenharmony_ci * Actually spawn the process and compile the module. 1191cb0ef41Sopenharmony_ci */ 1201cb0ef41Sopenharmony_ci 1211cb0ef41Sopenharmony_ci async function doBuild () { 1221cb0ef41Sopenharmony_ci // Enable Verbose build 1231cb0ef41Sopenharmony_ci const verbose = log.logger.isVisible('verbose') 1241cb0ef41Sopenharmony_ci let j 1251cb0ef41Sopenharmony_ci 1261cb0ef41Sopenharmony_ci if (!win && verbose) { 1271cb0ef41Sopenharmony_ci argv.push('V=1') 1281cb0ef41Sopenharmony_ci } 1291cb0ef41Sopenharmony_ci 1301cb0ef41Sopenharmony_ci if (win && !verbose) { 1311cb0ef41Sopenharmony_ci argv.push('/clp:Verbosity=minimal') 1321cb0ef41Sopenharmony_ci } 1331cb0ef41Sopenharmony_ci 1341cb0ef41Sopenharmony_ci if (win) { 1351cb0ef41Sopenharmony_ci // Turn off the Microsoft logo on Windows 1361cb0ef41Sopenharmony_ci argv.push('/nologo') 1371cb0ef41Sopenharmony_ci } 1381cb0ef41Sopenharmony_ci 1391cb0ef41Sopenharmony_ci // Specify the build type, Release by default 1401cb0ef41Sopenharmony_ci if (win) { 1411cb0ef41Sopenharmony_ci // Convert .gypi config target_arch to MSBuild /Platform 1421cb0ef41Sopenharmony_ci // Since there are many ways to state '32-bit Intel', default to it. 1431cb0ef41Sopenharmony_ci // N.B. msbuild's Condition string equality tests are case-insensitive. 1441cb0ef41Sopenharmony_ci const archLower = arch.toLowerCase() 1451cb0ef41Sopenharmony_ci const p = archLower === 'x64' 1461cb0ef41Sopenharmony_ci ? 'x64' 1471cb0ef41Sopenharmony_ci : (archLower === 'arm' 1481cb0ef41Sopenharmony_ci ? 'ARM' 1491cb0ef41Sopenharmony_ci : (archLower === 'arm64' ? 'ARM64' : 'Win32')) 1501cb0ef41Sopenharmony_ci argv.push('/p:Configuration=' + buildType + ';Platform=' + p) 1511cb0ef41Sopenharmony_ci if (jobs) { 1521cb0ef41Sopenharmony_ci j = parseInt(jobs, 10) 1531cb0ef41Sopenharmony_ci if (!isNaN(j) && j > 0) { 1541cb0ef41Sopenharmony_ci argv.push('/m:' + j) 1551cb0ef41Sopenharmony_ci } else if (jobs.toUpperCase() === 'MAX') { 1561cb0ef41Sopenharmony_ci argv.push('/m:' + require('os').cpus().length) 1571cb0ef41Sopenharmony_ci } 1581cb0ef41Sopenharmony_ci } 1591cb0ef41Sopenharmony_ci } else { 1601cb0ef41Sopenharmony_ci argv.push('BUILDTYPE=' + buildType) 1611cb0ef41Sopenharmony_ci // Invoke the Makefile in the 'build' dir. 1621cb0ef41Sopenharmony_ci argv.push('-C') 1631cb0ef41Sopenharmony_ci argv.push('build') 1641cb0ef41Sopenharmony_ci if (jobs) { 1651cb0ef41Sopenharmony_ci j = parseInt(jobs, 10) 1661cb0ef41Sopenharmony_ci if (!isNaN(j) && j > 0) { 1671cb0ef41Sopenharmony_ci argv.push('--jobs') 1681cb0ef41Sopenharmony_ci argv.push(j) 1691cb0ef41Sopenharmony_ci } else if (jobs.toUpperCase() === 'MAX') { 1701cb0ef41Sopenharmony_ci argv.push('--jobs') 1711cb0ef41Sopenharmony_ci argv.push(require('os').cpus().length) 1721cb0ef41Sopenharmony_ci } 1731cb0ef41Sopenharmony_ci } 1741cb0ef41Sopenharmony_ci } 1751cb0ef41Sopenharmony_ci 1761cb0ef41Sopenharmony_ci if (win) { 1771cb0ef41Sopenharmony_ci // did the user specify their own .sln file? 1781cb0ef41Sopenharmony_ci const hasSln = argv.some(function (arg) { 1791cb0ef41Sopenharmony_ci return path.extname(arg) === '.sln' 1801cb0ef41Sopenharmony_ci }) 1811cb0ef41Sopenharmony_ci if (!hasSln) { 1821cb0ef41Sopenharmony_ci argv.unshift(gyp.opts.solution || guessedSolution) 1831cb0ef41Sopenharmony_ci } 1841cb0ef41Sopenharmony_ci } 1851cb0ef41Sopenharmony_ci 1861cb0ef41Sopenharmony_ci if (!win) { 1871cb0ef41Sopenharmony_ci // Add build-time dependency symlinks (such as Python) to PATH 1881cb0ef41Sopenharmony_ci buildBinsDir = path.resolve('build', 'node_gyp_bins') 1891cb0ef41Sopenharmony_ci process.env.PATH = `${buildBinsDir}:${process.env.PATH}` 1901cb0ef41Sopenharmony_ci await fs.mkdir(buildBinsDir, { recursive: true }) 1911cb0ef41Sopenharmony_ci const symlinkDestination = path.join(buildBinsDir, 'python3') 1921cb0ef41Sopenharmony_ci try { 1931cb0ef41Sopenharmony_ci await fs.unlink(symlinkDestination) 1941cb0ef41Sopenharmony_ci } catch (err) { 1951cb0ef41Sopenharmony_ci if (err.code !== 'ENOENT') throw err 1961cb0ef41Sopenharmony_ci } 1971cb0ef41Sopenharmony_ci await fs.symlink(python, symlinkDestination) 1981cb0ef41Sopenharmony_ci log.verbose('bin symlinks', `created symlink to "${python}" in "${buildBinsDir}" and added to PATH`) 1991cb0ef41Sopenharmony_ci } 2001cb0ef41Sopenharmony_ci 2011cb0ef41Sopenharmony_ci const proc = gyp.spawn(command, argv) 2021cb0ef41Sopenharmony_ci await new Promise((resolve, reject) => proc.on('exit', async (code, signal) => { 2031cb0ef41Sopenharmony_ci if (buildBinsDir) { 2041cb0ef41Sopenharmony_ci // Clean up the build-time dependency symlinks: 2051cb0ef41Sopenharmony_ci await fs.rm(buildBinsDir, { recursive: true }) 2061cb0ef41Sopenharmony_ci } 2071cb0ef41Sopenharmony_ci 2081cb0ef41Sopenharmony_ci if (code !== 0) { 2091cb0ef41Sopenharmony_ci return reject(new Error('`' + command + '` failed with exit code: ' + code)) 2101cb0ef41Sopenharmony_ci } 2111cb0ef41Sopenharmony_ci if (signal) { 2121cb0ef41Sopenharmony_ci return reject(new Error('`' + command + '` got signal: ' + signal)) 2131cb0ef41Sopenharmony_ci } 2141cb0ef41Sopenharmony_ci resolve() 2151cb0ef41Sopenharmony_ci })) 2161cb0ef41Sopenharmony_ci } 2171cb0ef41Sopenharmony_ci} 2181cb0ef41Sopenharmony_ci 2191cb0ef41Sopenharmony_cimodule.exports = build 2201cb0ef41Sopenharmony_cimodule.exports.usage = 'Invokes `' + (win ? 'msbuild' : 'make') + '` and builds the module' 221