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., #include
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.
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 ^ and < can
evaluate to filenames that do not occur in the makefile. The
filter and filter-out functions can help solve
these problems.
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 .cmd
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
the 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.
The ACCESS_CMD variable is useful, for example, when
porting the Linux-kernel's build process from make to
amake. By design, its top-level makefiles build a
target in a subdirectory by changing to that subdirectory
and re-executing 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
in a .dep file, which is a simple makefile. Its name
is the target's name, with a .dep suffix.
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 .sib
suffix.
If the target cache is enabled, siblings are cached, along with targets.
SHELL=/bin/bash
ACCESS_ENABLE:=1
foo:
wc /etc/hosts > $
sinclude *.dep
This is the resulting foo.dep:
foo: /etc/hosts
foo: /usr/bin/wc
This is the resulting foo.cmd:
#!/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