1'use strict'; 2 3// Usage: e.g. node build-addons.js <path to node-gyp> <directory> 4 5const child_process = require('child_process'); 6const path = require('path'); 7const fs = require('fs').promises; 8const util = require('util'); 9 10const execFile = util.promisify(child_process.execFile); 11 12const parallelization = +process.env.JOBS || require('os').cpus().length; 13const nodeGyp = process.argv[2]; 14 15async function runner(directoryQueue) { 16 if (directoryQueue.length === 0) 17 return; 18 19 const dir = directoryQueue.shift(); 20 const next = () => runner(directoryQueue); 21 22 try { 23 // Only run for directories that have a `binding.gyp`. 24 // (https://github.com/nodejs/node/issues/14843) 25 await fs.stat(path.join(dir, 'binding.gyp')); 26 } catch (err) { 27 if (err.code === 'ENOENT' || err.code === 'ENOTDIR') 28 return next(); 29 throw err; 30 } 31 32 console.log(`Building addon in ${dir}`); 33 const { stdout, stderr } = 34 await execFile(process.execPath, [nodeGyp, 'rebuild', `--directory=${dir}`], 35 { 36 stdio: 'inherit', 37 env: { ...process.env, MAKEFLAGS: '-j1' } 38 }); 39 40 // We buffer the output and print it out once the process is done in order 41 // to avoid interleaved output from multiple builds running at once. 42 process.stdout.write(stdout); 43 process.stderr.write(stderr); 44 45 return next(); 46} 47 48async function main(directory) { 49 const directoryQueue = (await fs.readdir(directory)) 50 .map((subdir) => path.join(directory, subdir)); 51 52 const runners = []; 53 for (let i = 0; i < parallelization; ++i) 54 runners.push(runner(directoryQueue)); 55 return Promise.all(runners); 56} 57 58main(process.argv[3]).catch((err) => setImmediate(() => { throw err; })); 59