Boost C++ Libraries



Bugs, Limitations

In addition to generic error messages, b2 may emit one of the following:

warning: unknown rule X

A rule was invoked that has not been defined with an "actions" or "rule" statement.

using N temp target(s)

Targets marked as being temporary (but nonetheless present) have been found.

updating N target(s)

Targets are out-of-date and will be updated.

can't find N target(s)

Source files can't be found and there are no actions to create them.

can't make N target(s)

Due to sources not being found, other targets cannot be made.

warning: X depends on itself

A target depends on itself either directly or through its sources.

don't know how to make X

A target is not present and no actions have been defined to create it.

X skipped for lack of Y

A source failed to build, and thus a target cannot be built.

warning: using independent target X

A target that is not a dependency of any other target is being referenced with $(<) or $(>).

X removed

B2 removed a partially built target after being interrupted.

For parallel building to be successful, the dependencies among files must be properly spelled out, as targets tend to get built in a quickest-first ordering. Also, beware of un-parallelizable commands that drop fixed-named files into the current directory, like yacc(1) does.

A poorly set $(JAMSHELL) is likely to result in silent failure.

This section is derived from the official Jam documentation and from experience using it and reading the Jambase rules. We repeat the information here mostly because it is essential to understanding and using Jam, but is not consolidated in a single place. Some of it is missing from the official documentation altogether. We hope it will be useful to anyone wishing to become familiar with Jam and the Boost build system.

  • Jam "rules" are actually simple procedural entities. Think of them as functions. Arguments are separated by colons.
  • A Jam target is an abstract entity identified by an arbitrary string. The build-in DEPENDS rule creates a link in the dependency graph between the named targets.
  • Note that the original Jam documentation for the built-in INCLUDES rule is incorrect: INCLUDES targets1 : targets2 causes everything that depends on a member of targets1 to depend on all members of targets2. It does this in an odd way, by tacking targets2 onto a special tail section in the dependency list of everything in targets1. It seems to be OK to create circular dependencies this way; in fact, it appears to be the "right thing to do" when a single build action produces both targets1 and targets2.
  • When a rule is invoked, if there are actions declared with the same name as the rule, the actions are added to the updating actions for the target identified by the rule's first argument. It is actually possible to invoke an undeclared rule if corresponding actions are declared: the rule is treated as empty.
  • Targets (other than NOTFILE targets) are associated with paths in the file system through a process called binding. Binding is a process of searching for a file with the same name as the target (sans grist), based on the settings of the target-specific SEARCH and LOCATE variables.
  • In addition to local and global variables, jam allows you to set a variable on a target. Target-specific variable values can usually not be read, and take effect only in the following contexts:

    • In updating actions, variable values are first looked up on the target named by the first argument (the target being updated). Because Jam builds its entire dependency tree before executing actions, Jam rules make target-specific variable settings as a way of supplying parameters to the corresponding actions.
    • Binding is controlled entirely by the target-specific setting of the SEARCH and LOCATE variables, as described here.
    • In the special rule used for header file scanning, variable values are first looked up on the target named by the rule's first argument (the source file being scanned).
  • The "bound value" of a variable is the path associated with the target named by the variable. In build actions, the first two arguments are automatically replaced with their bound values. Target-specific variables can be selectively replaced by their bound values using the bind action modifier.
  • Note that the term "binding" as used in the Jam documentation indicates a phase of processing that includes three sub-phases: binding (yes!), update determination, and header file scanning. The repetition of the term "binding" can lead to some confusion. In particular, the Modifying Binding section in the Jam documentation should probably be titled "Modifying Update Determination".
  • "Grist" is just a string prefix of the form <characters>. It is used in Jam to create unique target names based on simpler names. For example, the file name "test.exe" may be used by targets in separate subprojects, or for the debug and release variants of the "same" abstract target. Each distinct target bound to a file called "test.exe" has its own unique grist prefix. The Boost build system also takes full advantage of Jam's ability to divide strings on grist boundaries, sometimes concatenating multiple gristed elements at the beginning of a string. Grist is used instead of identifying targets with absolute paths for two reasons:

    1. The location of targets cannot always be derived solely from what the user puts in a Jamfile, but sometimes depends also on the binding process. Some mechanism to distinctly identify targets with the same name is still needed.
    2. Grist allows us to use a uniform abstract identifier for each built target, regardless of target file location (as allowed by setting ALL_LOCATE_TARGET).
  • When grist is extracted from a name with $(var:G), the result includes the leading and trailing angle brackets. When grist is added to a name with $(var:G=expr), existing grist is first stripped. Then, if expr is non-empty, leading <s and trailing >s are added if necessary to form an expression of the form <expr2>; <expr2> is then prepended.
  • When Jam is invoked it imports all environment variable settings into corresponding Jam variables, followed by all command-line (-s...) variable settings. Variables whose name ends in PATH, Path, or path are split into string lists on OS-specific path-list separator boundaries (e.g. ":" for UNIX and ";" for Windows). All other variables are split on space (" ") boundaries. Boost Jam modifies that behavior by allowing variables to be quoted.
  • A variable whose value is an empty list or which consists entirely of empty strings has a negative logical value. Thus, for example, code like the following allows a sensible non-empty default which can easily be overridden by the user:
    MESSAGE ?\= starting jam... ;
    if $(MESSAGE) { ECHO The message is: $(MESSAGE) ; }
    If the user wants a specific message, he invokes jam with "-sMESSAGE=message text". If he wants no message, he invokes jam with -sMESSAGE= and nothing at all is printed.
  • The parsing of command line options in Jam can be rather unintuitive, with regards to how other Unix programs accept options. There are two variants accepted as valid for an option:

    1. -xvalue, and
    2. -x value.