fear of code

Order-only prerequisites, finally understood

Every Makefile I had written rebuilt everything whenever the output directory was touched, and I had assumed that was simply how Make worked.

It is not. A prerequisite after a pipe is order-only: Make will build it first if it is missing, but will not consider its timestamp when deciding whether the target is out of date.

dist/site.tar.gz: $(SOURCES) | dist
	tar -czf $@ -C site .

dist:
	mkdir -p $@

Without the pipe, writing any file into dist updates the directory's modification time, which makes the archive look stale, which rebuilds it, which updates the directory again. The loop is stable rather than infinite, so it never announces itself — the build is just always dirty.

It is documented clearly. I had read that page more than once and skipped the section because I did not know I needed it.

All notes · Front page