The features of amake are implemented by changing
make in several places:
access_commands function writes a shell script
containing commands-executed dependencies to a file. The
script can be executed to update the target. It contains the
sequence of commands from the target's makefile rule. It
also contains a sequence of environment-variable assignments
(or unset commands) to provide a suitable execution
environment. The file's name is the target's name, with
.cmd appended. A .cmd file is not created if
it already exists with the same content. If the content of
the new .cmd file differs from the content of the
existing .cmd file, and the ACCESS_ANYCMD
makefile variable is not set, the target is updated.
access_mustmake function determines
whether the target must be updated due to a dependency's
checksum or last-modification-time, using exact
equality. The relevant variables are ACCESS_CHKSUM
and ACCESS_LMTIME. Otherwise, the usual make
older-than/newer-than relative comparison is used.
access_cache function searches the cache
for a suitable target. If one is found, it is retrieved and
the update is complete.
access_open
function creates an anonymous pipe and a pipe-arbitrating
semaphore for communication with a script named
amake-collect. It then calls fork and
exec to execute the script. amake-collect is
described in Amake-Collect, but its purpose is to
create the target's .dep and .sib files.
access_child
function sets two environment variables, to influence the
command's execution. The first is LD_PRELOAD, so the
libaccess wrappers are executed. The second variable
is set to a sequence of pipe-descriptor/semaphore-identifier
pairs. This allows a wrapper to write programs-executed and
files-accessed dependencies to one or more instances of
amake-collect, through that many pipes. Recursive
make execution and parallel building require multiple
processes to write to the same pipe, even though there is
exactly one reader process for a particular pipe. SVR4
semaphores allow writer processes to synchronize pipe
access.
access_close function closes the last open pipe
descriptor, allowing amake-collect to detect an
end-of-file condition on its pipe. It also removes the
pipe's semaphore and waits for amake-collect to
exit. Finally, if the target cache is enabled, the updated
target is put in the cache.