Make in Prolog 2: Hashes
Kovacsics Robert
Part two of Make in Prolog. This is extending the make implementation with using hashes of inputs instead of modification time for out-of-date detection.
Path Patterns
But first, a discussion on matching on paths. In the previous implementation I used a representation of paths that has some flags in it. Let me show the pathology by studying a few simple paths.
- The simplest is
main.cpp, which doesn’t work in the build system because we use the patternDirs/Fileso you have to use'.'/main.cpp. - The
path_segments_atomtranslates into a left-associative(a/b)/cwhich is contrary to expectations and actual the filesystem hierarchy. (Which isa/(b/c)to be clear). This makes matching on filenames easy but makes adding a root directory (or checking the root directory) inconvenient.
The first issue is going away here as we will put the sources into the src
directory (and use build for build files).
For now let’s just add a helper to get the root component of the path – I wanted to point the issues out but addressing it is out of scope for now.
make.plrootdir(A/B, Root, Rest/B) :- rootdir(A, Root, Rest), !. rootdir(A/B, A, B).
This never mentions a path without / because it is meant to fail on that,
and retry for the last clause to return the root. The cut is there to prevent
backtracking and returning multiple directories for root.
Hashes
The overall strategy is that if we have build rules
deps(Base:elf, [Base:obj]).
deps(Base:obj, [Base:cpp]).
build(Path:elf, Deps) :- system(gcc, ['-o', Path:elf | Deps]).
build(Dest:obj, [Src:cpp | Rest]) :-
system('g++', ['-c', '-o', Dest:obj, Src:cpp | Rest]).then make(src/main:elf) will
- deduce it needs to
build/main-Hash1:elf; - which needs
build/main-Hash2:obj; - likewise
build/main-Hash3:cpp, which it can grab fromsrc/main:cppand use the hash for the contents of the file; - then it can build
build/main-Hash2:objusingbuild/main-Hash3:cpp, and using the input paths (not the input contents – already captured by their hash1); - likewise
build/main-Hash1:elffrombuild/main-Hash2:obj; - and finally copy
build/main-Hash1:elftosrc/main:elf.
The code for this at
https://git.kovirobi.uk/kovirobi/prolog-make/src/branch/hash on branch
hash this time.
This depends on reproducible builds, not the case if you use e.g.
__DATE__or__TIME__withoutSOURCE_DATE_EPOCH, see the-Wdate-timeoption of GCC. ↩︎