@@ -42,7 +42,7 @@ Consider a sample C project with two `.c` files:
Since each `.c` file is compiled into a corresponding `.o` file, `util.o` depends on `util.c` and `main.o` depends on `main.c`.
Note that both `util.c` and `main.c` include `util.h`, so both `util.o` and `main.o` depend on `util.h`.
`program`, the final
`program`, the resulting executable file, depends on `util.o` and `main.o`.
We can represent these relationships with a "dependency graph", where each file points to the files it depends on:
```
...
...
@@ -70,7 +70,7 @@ def build(target):
fordependencyinget_dependencies(target):
build(dependency)
# Now that dependencies are up to date, we can build the target
run(get_build_command(target))
run_command(get_build_command(target))
```
Since `build()` waits to return until `target` is built, only one build command will run at a time!
...
...
@@ -82,7 +82,7 @@ Implement `make` **asynchronously** in Node.js.
### Rules
Your program will be run as `node make.js makefile.js target1 ... targetN`.
Your program will be run as `npm run make makefile.js target1 ... targetN`.
`makefile.js` is a Node.js file that exports an array of all available rules to build files.
Each rule has the following structure:
```ts
...
...
@@ -124,9 +124,9 @@ Additional requirements:
- Files should be built at most once.
For example, if `A` depends on `B` and `C`, and both `B` and `C` depend on `D`, building `A` should only build `D` once.
- Files should only be rebuilt if necessary.
Specifically, a file needs to be built if it doesn't exist, or if any of its dependencies was changed since the target was last built.
Specifically, a file needs to be built if it doesn't exist, or if any of its dependencies were changed since the target was last built.
(You can use the "last modified time" that all files have to tell whether any dependencies are newer than the target.)
Note that a file also needs to be rebuilt if an indirect dependency is modified.
Note that if an indirect dependency is modified, one of the target's dependencies will be rebuilt, so the target also needs to be rebuilt.
For example, if `A` depends on `B` and `B` depends on `C`, then if `C` is updated, `B` needs to be rebuilt and then `A` does too.
- Files should be built as soon as possible (i.e. as soon as all their dependencies are up to date).
- Like `make`, print out each command before executing it.
...
...
@@ -176,5 +176,5 @@ Child processes can be created using [`child_process.execFile()`](https://nodejs
We use [`util.promisify()`](https://nodejs.org/api/util.html#util_util_promisify_original) to make `execFile()` return a `Promise` instead of using a callback function.
This, along with printing out the command and its output, is already done by `runCommand()` in the starter code.
You can use `process.exit(statusCode)` to exit the process with the given code.
You can use [`process.exit(statusCode)`](https://nodejs.org/api/process.html#process_process_exit_code) to exit the process with the given code.
If the code is non-zero, it indicates that `make.js` failed.