make -j and -C: Parallel Builds and Targets
make -j<N> runs recipe commands in parallel and make -C <dir> runs make in another directory, the two flags that matter most in CI.
GNU Make (often invoked as make or gmake) is still the backend for autotools and many hand-written projects. In CI the wins come from -j parallelism and -C for out-of-tree invocation.
What it does
make reads a Makefile and builds the requested targets, running recipes for anything out of date. -j<N> runs up to N recipes concurrently; without a number, -j runs unlimited jobs. -C changes into a directory first, letting you build from anywhere.
Common usage
make -j$(nproc)
make -C build -j4
make -C build test
make clean allOptions
| Flag | What it does |
|---|---|
| -j [N] | Run N jobs in parallel (no N = unlimited) |
| -C <dir> | Change to <dir> before reading the Makefile |
| -f <file> | Use a Makefile other than ./Makefile |
| -k | Keep going after a failed target |
| -B | Unconditionally rebuild all targets |
| -n | Dry run: print recipes without executing them |
In CI
Pass an explicit -j$(nproc); bare -j (unlimited) can fork thousands of compilers and exhaust runner memory. On some systems make is BSD make and lacks GNU features; use gmake explicitly. Recursive makefiles that spawn sub-makes need the job server, so keep the top-level -j and let sub-makes inherit it via +.
Common errors in CI
"make: * No rule to make target 'foo', needed by 'bar'. Stop." means a missing prerequisite file or a wrong target name. "make: * [Makefile:12: build] Error 1" is a recipe command that returned non-zero; scroll up for the real error. "warning: jobserver unavailable: using -j1" means a sub-make was invoked without the + prefix, so parallelism collapsed. "Makefile:1: *** missing separator. Stop." means spaces were used where a tab is required.