Next: , Previous: Usage, Up: Amake Features

13.2 Operation

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.

Here's an example makefile:

             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