make.js 1.99 KB
const {execFile} = require('child_process')
const path = require('path')
const {promisify} = require('util')

// If running as `npm run make`, use the current directory the command was run in
const {INIT_CWD} = process.env
if (INIT_CWD) process.chdir(INIT_CWD)

// A version of child_process.execFile() that returns a Promise
const exec = promisify(execFile)
/**
 * Creates a Promise representing running the given command.
 * For example, runCommand(['clang', '-c', 'main.c']) runs `clang -c main.c`.
 * The returned Promise resolves when the command finishes.
 * If the command fails, the returned Promise rejects with the error.
 * Also prints the command and any output the program produces.
 */
function runCommand(command) {
  console.log(command.join(' '))
  const [program, ...args] = command
  return exec(program, args)
    .then(({stdout, stderr}) => {
      process.stdout.write(stdout)
      process.stderr.write(stderr)
    })
}

const [recipesFile, ...targets] = process.argv.slice(2)
if (!recipesFile) throw new Error('Usage: npm run make makefile.js target1 ... targetN')

/* We get the exports from `recipesFile` using require().
 * require() is blocking, but this is okay
 * because we can't do anything until `recipesFile` is processed. */
const recipes = require(path.resolve(recipesFile))

// Map of build targets to their recipes
const recipeMap = new Map()
// TODO: build `recipeMap` from `recipes`

// Map of build targets to Promises representing their build process.
// This allows you to reuse these Promises if multiple targets have the same dependencies.
const buildPromises = new Map()

/**
 * Creates a Promise representing building the given target.
 * Should use the Promise in `buildPromises` for this target if it exists,
 * and store the new Promise in `buildPromises`.
 *
 * @param target the target file to build
 * @return a Promise that resolves when `target` has been built
 */
function makeBuildPromise(target) {
  // TODO
}

// TODO: use makeBuildPromise() to build all the requested targets