• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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