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.