16.2.4 DEFSYSTEM rules

Rules may be defined in a system which modify the default behavior of that system, ensuring, for instance, that certain files are always loaded or compiled before others.

Rules apply to files and subsystems alike as members of their parent system, but are not inherited by subsystems.

When you invoke an action such as compiling a system, the following happens by default:

Each member of the system is considered in turn, in the order they are given in the system definition.

If the member is itself a system then the action is performed on that system too, and so on recursively.

If the member is a file and action-specific constraints are satisfied, the file action is inserted into a
plan.

For example, in the case of compiling, a "compile this file" event is put into the plan if the source file is newer than the object file.

After the plan has been assembled, it can be viewed or executed.

This behavior can be modified by describing dependencies between the members using
rules
. These are specified using the
:rules keyword to defsystem.

A rule has three components:

The target(s).

The action that is performed if the rule executes successfully.

This is an action-member description like
:compile "foo"
. The member can be an actual member of the system or
:all (meaning the rule should apply to each member of the system).

The actions that the target(s) are
:caused-by.

The actions that cause the rule to execute successfully.

This is a list of action-member descriptions. The member of each of these descriptions should be either a real system member, or
:previous
, which means all members listed before the member of the target in the system description.

If any of these descriptions are already in the current plan (as a result of other rules executing successfully, or as a result of default system behavior), they trigger successful execution of this rule.

The actions that the target(s)
:requires.

The actions that need to be performed before the rule can execute successfully.

This is a list of action-member descriptions that should be planned for before the action on the target(s). Again, each member should either be a real member of the system, or
:previous
.

The use of the keyword
:previous means, for example, that you can specify that in order to compile a file in the system, all the members that come before it must be loaded.

When the action and member of a target are matched during the traversal of the list of members, the target is inserted into the plan if either of the following are true:

any of the action-member descriptions in the
:caused-by
clause is already in the plan, or

any implicit conditions (such as the source file being newer than the object file) are satisfied.

If the target is put into the plan then other targets are inserted beforehand if the action-member description of any
:requires clause is not already in the plan.