3 ms·
If you trust yourself to capture the dependencies totally then it doesn't really matter whether you use make or redo, you could add the stdio.h dependency to ei
by Nullabillity 6y ago
If you trust yourself to capture the dependencies totally then it doesn't really matter whether you use make or redo, you could add the stdio.h dependency to either. But the only way to actually achieve reliable clean-less builds is to run it in an environment where you either take away all access to non-dependencies (like Nix[0]) or automatically record all accessed files (like Tup[1]).
GCC also supports emitting header lists in a format that Make understands, but that won't cover non-GCC targets, or be as comprehensive as doing it in the build system.
[0]: https://nixos.org/ https://nixos.org/
[1]: http://gittup.org/tup/ http://gittup.org/tup/
- jnxx 6y ago> But the only way to actually achieve reliable clean-less builds is to run it in an environment where you either take away all access to non-dependencies (like Nix[0]) or automatically record all accessed files (like Tup[1]). You can also let the compiler record dependencies. Gcc, for example, does have an option for that. That's explained here: https://redo.readthedocs.io/en/latest/#whats-so-special-about-redo https://redo.readthedocs.io/en/latest/#whats-so-special-abou...
- jnxx 6y agoTo mention, I think Nix or Guix are indeed good complements to things like redo! Guix System and NixOS are just geared to define the whole system, while make or redo build a single program or a set of artifacts.
- jlokier 6y agoGCC actually gets it wrong, as does almost every compiler and makefile combination. Consider this realistic example. Realistic in that I've encountered it in the real world and seen buggy demos shipped because of it, with non-reproducible bugs. We have a search path for headers, like so: -Imyinc -I../dep1/inc -Idep2/inc -I/usr/include We compile a source file which contains: #include "creative.h" GCC outputs a dependency which is read into the Makefile next time: object.o: ../dep2/inc/creative.h Looks good! Later that day we update from our upstream dependencies: git pull Which adds a file ../dep1/inc/creative.h Recompiling, the project works: make ... make test => 144,123 pass, 0 fail - well done, you earned a coffee! We captured automatic dependencies, this should be good to ship. But no: make clean ... make ... make test => FAIL! What happened? Turns out someone upstream moved (by copying) creative.h to ../dep1/inc and forgot to remove the old copy in ../dep2/inc. Then someone edited a data structure in that file. Automatic dependencies gave everyone false confidence in the build results seen by different people. That kind of automatic dependency is insufficient because it doesn't capture "negative file results" during path searches, where output depends on a file not existing, and changes if a new file is created. It is possible to use Makefiles with this handled accurately in the automatic dependency tracking, but I haven't seen it done often. An equivalent problem occurs in caches which automatically track data dependencies used to generate results. For example web pages generated from a combination of files, templates and data, build artifacts such as container/VM images, or at a much lower level, data dependencies inside calculations with conditional branches. To do caching right, they must validate negative tests as well as positive that arise in searches. I've seen a surprising number of cache implementations which don't try particularly hard to get this right.