This is the documentation of version 1.50. You may want the documentation of the stable version (2.0) or of the well tested 2.1 development snapshot or our homepage.

Makepp Build Check Methods

How makepp decides to rebuild files

A: architecture_independentE: exact_matchI: ignore_actionO: only_actionT: target_newer

Makepp stores a variety of information about how any given file was built the last time. This information includes the build command, the architecture, and the signatures of all the file's dependencies. (All the stored information is in the subdirectory .makepp of each directory.) If any of this information has changed, makepp usually decides to rebuild the file. The build check method is what controls makepp's decision to rebuild. It decides which information to look at, and which to ignore.

Makepp usually picks the correct build check method automatically. However, you can change the signature method for an individual rule by using :build_check modifier on the rule, or for all rules in a makefile by using the build_check statement, or for all makefiles at once using the -m or --build-check-method command line option.

The data used to decide about a rebuild or a repository or build cache import is stored in the internal build info file. You can display it with makeppinfo, mppi. Below each method gives an example of how to see its keys.

Build check methods included in the distribution

At present, there are five build check methods included in the distribution:

exact_match

This method uses the modification dates on the file as signatures. It rebuilds the targets unless all of the following conditions are true:

exact_match is the default method unless you are rebuilding a Makefile (see below). This is a highly reliable way of ensuring correct builds, and is almost always what you want. However, it does have a few side effects that may be surprising:

Concretely, a file will not be rebuilt, or can be fetched from repository or build cache, if the following command output stays the same, i.e. matches the signatures of the dependencies:

mppi -k'COMMAND ARCH SORTED_DEPS DEP_SIGS ENV_{DEP,VAL}S' file
architecture_independent

The architecture_independent method is the same as exact_match except that it does not check the architecture. This can be useful for architecture-independent files, that don't need to be rebuilt when you switch to a different architecture. For example, you probably don't need to rerun bison on solaris if you already ran it on linux.

The architecture_independent method is best used by specifying it using the :build_check architecture_independent modifier to the each rule that produces architecture independent files. Makepp by default never assumes any files are architecture independent, because even .c files can be architecture dependent. For example, the output of solaris lex will not compile under linux, or at least it wouldn't last time I tried. So you must manually specify this build check method for any files which are truly architecture-independent.

Concretely, a file will not be rebuilt, or can be fetched from repository or build cache, if the following command output stays the same, i.e. matches the signatures of the dependencies:

mppi -k'COMMAND SORTED_DEPS DEP_SIGS ENV_{DEP,VAL}S' file
ignore_action

The ignore_action method is the same as exact_match except that it does not check the action string (the command). Sometimes a command can change and you don't want to force a rebuild.

For example, you might want to explicitly put a date into your command to log when the build was done, but you don't want to force a rebuild every time the command is executed. For example,

BUILD_DATE := $(shell date)
my_program : $(MODULES).o
    $(CXX) $(inputs) -DBUILD_DATE="\"$(BUILD_DATE)\"" date_stamp.c -o $(output)

This will compile date_stamp.c with the last build date stamp, but won't force a recompile when the date changes. Unfortunately, if something else about the link command changes (e.g., you change linker options), it also won't trigger a rebuild.

This is also useful in conjunction with the $(changed_inputs) or $? variable for actions that merely update a target, rather than rebuilding it from scratch. For example, you could update a .a file like this:

libmine.a : *.o : build_check ignore_action
    $(AR) ru $(output) $(changed_inputs)

This will still mostly work if you forget to specify the : build_check ignore_action. However, suppose that none of the .o files have changed. The command will now be ar ru libmine.a which is probably different from what it was last time (e.g., ar ru libmine.a buggy_module.o), so makepp will run the command. In this case, the command won't do anything except waste time.

Building .a files like this is discouraged, because it can leave stale .o files inside the archive. If you delete a source file, the .o file is still inside the .a file, and this can lead to incorrect builds. It's better to build a .a file like this:

libmine.a : *.o
    &rm $(output)
    $(AR) ru $(output) $(inputs)

Concretely, a file will not be rebuilt, or can be fetched from repository or build cache, if the following command output stays the same, i.e. matches the signatures of the dependencies:

mppi -k'ARCH SORTED_DEPS DEP_SIGS ENV_{DEP,VAL}S' file
target_newer

The target_newer method looks only at the file date. If any dependency is more recent than the target, the target is rebuilt. This is the algorithm that the traditional unix make utility uses.

The target_newer method isn't as safe as the exact_match method because it won't trigger a rebuild if you change the build command, or if you replace a file with an older version. Sometimes also it can get confused if clocks are not properly synchronized. For example, if a file somehow gets a date of June 4, 2048, then between now and 2048, every file that depends on that file will be rebuilt even though the file doesn't change. Also switching to a different architecture won't trigger a rebuild. It prevents fetching a rule's target from a build cache, because there is no unique signature that can be associated to the endless set of pairs fulfilling the relationship newer than.

But there are a few cases where you may want to use the target_newer method:

If you need to manually check the timestamps, see makeppinfo examples for how to get the path of each dependency.

only_action

The very specific only_action method will only execute the action if the command string differs from the last time it was executed. For example,

$(ROOT)/include/%.h : %.h
    &ln -fr $(input) $(output)

publishes a file, but does not repeat this when the file changes. Note that the &ln command is builtin and thus cheap, but makepp still has to fork off and monitor a process to perform the whole action. So if you have lots of files to publish, there is still a benefit. Actually we did not specify the method, because, when the target is a symbolic link, this build check gets used automatically. You only need to specify it for other commands that depend solely on the command (which usually contains the names of the inputs):

%.list : %.x : build_check only_action
    &echo $(inputs) -o $(output)

Concretely, a file will not be rebuilt, or can be fetched from repository or build cache, if the following command output stays the same, i.e. matches the signatures of the dependencies:

mppi -kCOMMAND file

Other build check methods are possible. You can write your own build check method by creating a module Mpp::BuildCheck::MyMethod. Read the documentation in Mpp/BuildCheck.pm in the makepp distribution. Most likely, you will want your build check method to inherit from Mpp::BuildCheck::exact_match, so read its documentation too.

It's more commonly useful modify the signature mechanism than to modify the build check mechanism directly. Before you change the build check mechanism, see if your problem is better served by changing signatures (see the makepp_signatures manpage for details).

Here are some reasons why a custom build check method might be useful:


Last modified: 2011-01-23