In order to determine whether a target needs to be updated,
amake monitors and records files accessed, commands
executed, programs executed, shared libraries opened, and
environment-variable values. The need for files-accessed
dependencies should be obvious. Commands-executed
dependencies eliminate the need for a target to depend on
its makefile. Programs-executed and shared-libraries-opened
dependencies are important when tools are being modified.
Environment-variable-value dependencies are like
commands-executed dependencies, but are also important when
a target is built by different users, because such values
can affect tool execution.
There are several ad-hoc methods of approximating
files-accessed dependencies See Automatic Prerequisites. For example, source files can be scanned for
syntactic evidence of access (e.g.,
directives) or a tool can log accessed files (e.g.,
gcc -MMD). These methods are not really automatic.
amake detects files-accessed and programs-executed
dependencies via the shared-library
libaccess contains wrapper functions for the C
standard library functions that access or execute
files. Indirectly, the wrappers inform
amake of each
file access or execution.
Automatic-dependency analysis can lead to
surprises. Perhaps, the biggest surprise is that the
automatic makefile variables
evaluate to filenames that do not occur in the makefile. The
filter-out functions can help solve
The difference between a command-executed dependency and a program-executed dependency is that the command may be a complex sequence of shell builtins interspersed with regular program executions. A command is a character string. A program is a version of a file (i.e., with a timestamp or checksum).
amake records a target's commands-executed, and
environment-variable-value dependencies in a
file, which is an executable shell script. Its name is the
target's name, with a
.cmd suffix. You can execute
the script to update the target.
The file also contains a comment identifying the name and line number of the makefile containing the rule containing the commands. This information is very valuable for debugging makefiles.
The content of a
.cmd file can be ignored by setting
ACCESS_CMD makefile variable. This is useful when
a target can be built in more than one way. A better
solution is to change the makefile to build each target in
only one way.
ACCESS_CMD variable is useful, for example, when
porting the Linux-kernel's build process from
amake. By design, its top-level makefiles build a
target in a subdirectory by changing to that subdirectory
make. Its sub-level makefiles build
the same target by, typically, executing the compiler.The
ACCESS_CMD variable prevents
amake from always
rebuilding such a target.
amake records a target's files-accessed,
programs-executed, and shared-libraries-opened dependencies
.dep file, which is a simple makefile. Its name
is the target's name, with a
.dep file can also contain makefile-variable
definitions that record the checksum and/or
last-modification time of each dependency.
A sibling is a file that is created, as a side effect, while
creating a target. More precisely, a sibling is a
file/directory that is accessed and changed between the time
amake begins executing a target's commands and when
amake is done updating the target. The names of a
target's siblings are stored in its
.sib file, the
name of which is the target's name, with a
If the target cache is enabled, siblings are cached, along with targets.
Here's an example makefile:
SHELL=/bin/bash ACCESS_ENABLE:=1 foo: wc /etc/hosts > $ sinclude *.dep
This is the resulting
foo: /etc/hosts foo: /usr/bin/wc
This is the resulting
#!/bin/bash -x # GNUmakefile:5 export PATH=/home/buff/amake/bin:/usr/bin:/bin export LD_LIBRARY_PATH=/home/buff/amake/lib32:/home/buff/amake/lib64 wc /etc/hosts > foo