💾 Archived View for ew.srht.site › en › 2022 › 20221218-redo-2.gmi captured on 2023-01-29 at 15:55:35. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2023-01-29)
-=-=-=-=-=-=-
Part 2: Automatic Recording of Dependencies on Header Files
Part 3: CFLAGS and friends, config.sh, compile.do
Part 4: CFLAGS and friends, env/VAR, default.run.do
Part 5: Auto-update BUILDDATE in version.h
Part 6: The yacc/bison problem: one call produces two artifacts
Part 7: Test: Generator for N source files
My code featured in this series can be found at
https://git.sr.ht/~ew/ew.redo/
The dependency tree produced in Part 1 does not record the fact, that hello.o must be rebuild if resources.h has changed. Of course we could add such a dependency in hello.do, however, we are lazy and we want the computer to take care of this. One way of doing this, is to nicely ask the compiler to produce this information. The compiler, or more precicely the preprocessor needs to evaluate all '#include' pragmas anyway, it is in the position to record, what it encountered along its course. Fortunately there are flags to instruct gcc to list the include dependencies:
shell$ gcc -MMD -MF hello.d -c -o hello.o hello.c shell$ cat hello.d hello.o: hello.c resources.h
The output rightfully states, that hello.o needs to be rebuild, if either hello.c or resources.h have changed. The output is formatted in makefile syntax, it can be included as is into a Makefile. In order to make this information known to redo, we are reading the content of the file back into our .do file and call "redo-ifchange" on the part after the colon ':'. The change occurs in "default.o.do" only, and I use shell variable editing to remove the part up to and including the colon.
# default.o.do redo-ifchange $2.c gcc -MMD -MF $2.d -o $3 -c $2.c read DEPS <$2.d redo-ifchange ${DEPS#*:}
With this change in place, the build proceeds including the new commands. The explicit dependency is also visible in the output of redo-dot.
shell$ redo clean redo clean (0.005s) shell$ redo -xx all + redo-ifchange hello + OBJS=hello.o resources.o + redo-ifchange hello.o resources.o + redo-ifchange hello.c + redo-ifchange resources.c + gcc -MMD -MF hello.d -o .redo.hello.o.3418330711.3 -c hello.c + read DEPS + redo-ifchange hello.c resources.h + gcc -MMD -MF resources.d -o .redo.resources.o.1173191576.3 -c resources.c + read DEPS + redo-ifchange resources.c redo . . hello.o (default.o.do) (0.086s) redo . . resources.o (default.o.do) (0.099s) + gcc -o .redo.hello.1878974086.3 hello.o resources.o redo . hello (0.159s) redo all (0.206s) shell$ redo-dot hello digraph d { rankdir=LR ranksep=2 splines=false // splines=ortho node[shape=rectangle] "hello" -> "hello.o" "hello.o" -> "hello.o.do" [style=dotted] "hello.o" -> "default.o.do" "resources.o" -> "resources.o.do" [style=dotted] "hello" -> "hello.do" "hello.o" -> "resources.h" "hello" -> "resources.o" "resources.o" -> "default.o.do" "resources.o" -> "resources.c" "hello.o" -> "hello.c" } shell$ LANG=C ls -al total 76 drwxr-xr-x 3 ew ew 4096 Oct 18 17:50 . drwxr-xr-x 5 ew ew 4096 Oct 18 16:16 .. -rw-r--r-- 1 ew ew 29 Oct 18 17:35 .gitignore drwxr-xr-x 2 ew ew 4096 Oct 18 17:50 .redo -rw-r--r-- 1 ew ew 48 Oct 17 20:36 all.do -rw-r--r-- 1 ew ew 58 Oct 18 17:23 clean.do -rw-r--r-- 1 ew ew 592 Oct 18 17:12 default.o.do -rwxr-xr-x 1 ew ew 16032 Oct 18 17:50 hello -rw-r--r-- 1 ew ew 108 Oct 17 16:19 hello.c -rw-r--r-- 1 ew ew 48 Oct 18 17:50 hello.d -rw-r--r-- 1 ew ew 150 Oct 18 16:19 hello.do -rw-r--r-- 1 ew ew 1304 Oct 18 17:50 hello.o -rw-r--r-- 1 ew ew 33 Oct 17 16:19 resources.c -rw-r--r-- 1 ew ew 44 Oct 18 17:50 resources.d -rw-r--r-- 1 ew ew 22 Oct 17 16:20 resources.h -rw-r--r-- 1 ew ew 1136 Oct 18 17:50 resources.o
In order to explicitly record the dependency to system include files like /usr/include/stdio.h, the flag "-MMD" can be changed to "-MD", if so desired.
Do not forget, to add '*.d' in .gitignore and clean.do.