see:
- https://ninja-build.org/manual.html#ref_dependencies
- https://fuchsia.dev/fuchsia-src/development/build/ninja_how#order-only_inputs
- https://github.com/ninja-build/ninja/blob/d60673d49e4facef8579eebeb818318c5b744b0b/src/graph.h#L239-L240
- https://www.gnu.org/software/make/manual/html_node/Prerequisite-Types.html
semantics of order-only deps:
- when deciding whether to rebuild a target, the mtimes (or existence) of order-only deps are not considered
- if the target is built (i.e. due to a normal prereq that was newer), it will wait on order-only deps
- even if the target is not built (i.e. up to date), order-only deps will be scheduled for building (if out of date)
in short: order-only deps need to exist but don't need to be up to date
- i.e. dep that you're not sensitive to the actual contents of...
- the example in the fuchsia docs (shared object; file needs to exist to link the final binary but isn't actually read until later, when the binary is run) is actually a pretty good one
- to be clear: you never build a target with "stale" order-only deps; you just skip rebuilding targets where the only "change" was newer order-only deps
put another way:
- if your order-only dep rebuilds and your target was deemed dirty and scheduled for building, your target will be built after your order-only dep
- but your order-only dep rebuilding does not, itself, cause a rebuild of your target
- i.e. possibilities are:
- order only deps followed by your target
- OR: order only deps
- order is maintained; your target will never be built before its order-only deps
some scenarios to check your understanding:
dirty() { touch $1; sleep 0.1; touch $2; } # make $1 out of date w.r.t. $2
make() { command make -j2; }
ninja() { command ninja -j2; }
check() { make; ninja; }foo (order only dep) |
hey (rdep) |
pre cmd | GNU Make | Ninja (same as Make) |
|---|---|---|---|---|
| non-existent | non-existent | rm foo hey |
foo → hey |
foo → hey |
| non-existent | dirty (newer pre-reqs) | rm foo; dirty hey Makefile |
foo → hey |
foo → hey |
| non-existent | up-to-date (all pre-reqs older) | rm foo; touch hey |
foo |
foo |
dirty/PHONY |
non-existent | dirty foo{,.inp}; rm hey |
foo → hey |
foo → hey |
dirty/PHONY |
dirty (newer pre-reqs) | dirty foo{,.inp}; dirty hey Makefile |
foo → hey |
foo → hey |
dirty/PHONY |
up-to-date (all pre-reqs older) | dirty foo{,.inp}; touch hey |
foo |
foo |
| up-to-date | non-existent | touch foo; rm hey |
hey |
hey |
| up-to-date | dirty (newer pre-reqs) | touch foo; dirty hey Makefile |
hey |
hey |
| up-to-date | up-to-date (all pre-reqs older) | touch foo; sleep 0.1; touch hey |