boost.png (6897 bytes) Home Libraries People FAQ More

PrevUpHomeNext

The build layer

Metatargets
Virtual targets

The build layer has just four main parts -- metatargets (abstract targets), virtual targets, generators and properties.

The build process includes those steps:

  1. Top-level code calls the generate method of a metatarget with some properties.

  2. The metatarget combines the requested properties with requirements and passes the result, together with the list of sources, to the generators.construct function

  3. A generator appropriate for the build properties is selected and its run method is called. The method returns a list of virtual targets

  4. The targets are returned to the top level code. They are converted into bjam targets (via virtual-target.actualize) and passed to bjam for building.

Metatargets

There are several classes derived from "abstract-target". The "main-target" class represents top-level main target, the "project-target" acts like container for all main targets, and "basic-target" class is a base class for all further target types.

Since each main target can have several alternatives, all top-level target objects are just containers, referring to "real" main target classes. The type is that container is "main-target". For example, given:

alias a ;
lib a : a.cpp : <toolset>gcc ;

we would have one-top level instance of "main-target-class", which will contain one instance of "alias-target-class" and one instance of "lib-target-class". The "generate" method of "main-target" decides which of the alternative should be used, and call "generate" on the corresponding instance.

Each alternative is a instance of a class derived from "basic-target". The "basic-target.generate" does several things that are always should be done:

  • Determines what properties should be used for building the target. This includes looking at requested properties, requirements, and usage requirements of all sources.

  • Builds all sources

  • Computes the usage requirements which should be passes back.

For the real work of constructing virtual target, a new method "construct" is called.

The "construct" method can be implemented in any way by classes derived from "basic-target", but one specific derived class plays the central role -- "typed-target". That class holds the desired type of file to be produces, and calls the generators modules to do the job.

This means that a specific metatarget subclass may avoid using generators at all. However, this is deprecated and we're trying to eliminate all such subsclasses at the moment.

Note that the build/targets.jam file contains an UML diagram which might help.

Virtual targets

Virtual targets correspond to the atomic things which can be updated. Each virtual target can be assigned an updating action -- instance of the action class. The action class, in turn, contains a list of source targets, properties, and a name of bjam action block which should be executed.

We try hard to never create equal instances of the virtual-target class. Each code which creates virtual targets passes them though the virtual-target.register function, which detects if a target with the same name, sources, and properties was created. In that case, existing target is returned.

When all virtual targets are produced, they are "actualized". This means that the real file names are computed, and the commands that should be run are generated. This is done by the virtual-target.actualize method and the action.actualize methods. The first is conceptually simple, while the second need additional explanation. The commands in bjam are generated in two-stage process. First, a rule with the appropriate name (for example "gcc.compile") is called and is given the names of targets. The rule sets some variables, like "OPTIONS". After that, the command string is taken, and variable are substitutes, so use of OPTIONS inside the command string become the real compile options.

Boost.Build added a third stage to simplify things. It's now possible to automatically convert properties to appropriate assignments to variables. For example, <debug-symbols>on would add "-g" to the OPTIONS variable, without requiring to manually add this logic to gcc.compile. This functionality is part of the "toolset" module.

Note that the build/virtual-targets.jam file contains an UML diagram which might help.

Above, we noted that metatargets are built with a set of properties. That set is represented with the property-set class. An important point is that handling of property sets can get very expensive. For that reason, we make sure that for each set of (name, value) pairs only one property-set instance is created. The property-set uses extensive caching for all operation, so most work is avoided. The property-set.create is the factory function which should be used to create instances of the property-set class.


PrevUpHomeNext