The first thing we did in the introduction was declaring a new target type:
import type ; type.register VERBATIM : verbatim ;
The type is the most important property of a target. Boost.Build can automatically generate necessary build actions only because you specify the desired type (using the different main target rules), and because Boost.Build can guess the type of sources from their extensions.
The first two parameters for the type.register
rule
are the name of new type and the list of extensions associated with
it. A file with an extension from the list will have the given target
type. In the case where a target of the declared type is generated
from other sources, the first specified extension will be used.
Sometimes you want to change the suffix used for generated targets
depending on build properties, such as toolset. For example, some compiler
uses extension elf
for executable files. You can use the
type.set-generated-target-suffix
rule:
type.set-generated-target-suffix EXE : <toolset>elf : elf ;
A new target type can be inherited from an existing one.
type.register PLUGIN : : SHARED_LIB ;
The above code defines a new type derived from
SHARED_LIB
. Initially, the new type inherits all the
properties of the base type - in particular generators and suffix.
Typically, you'll change the new type in some way. For example, using
type.set-generated-target-suffix
you can set the suffix for
the new type. Or you can write special a generator for the new type. For
example, it can generate additional metainformation for the plugin.
In either way, the PLUGIN
type can be used whenever
SHARED_LIB
can. For example, you can directly link plugins
to an application.
A type can be defined as "main", in which case Boost.Build will automatically declare a main target rule for building targets of that type. More details can be found later.
Sometimes, a file can refer to other files via some include system. To make Boost.Build track dependencies between included files, you need to provide a scanner. The primary limitation is that only one scanner can be assigned to a target type.
First, we need to declare a new class for the scanner:
class verbatim-scanner : common-scanner { rule pattern ( ) { return "//###include[ ]*\"([^\"]*)\"" ; } }
All the complex logic is in the common-scanner
class, and you only need to override the method that returns
the regular expression to be used for scanning. The
parentheses in the regular expression indicate which part
of the string is the name of the included file. Only the
first parenthesized group in the regular expression will be
recognized; if you can't express everything you want that
way, you can return multiple regular expressions, each of
which contains a parenthesized group to be matched.
After that, we need to register our scanner class:
scanner.register verbatim-scanner : include ;
The value of the second parameter, in this case
include
, specifies the properties that contain the list
of paths that should be searched for the included files.
Finally, we assign the new scanner to the VERBATIM
target type:
type.set-scanner VERBATIM : verbatim-scanner ;
That's enough for scanning include dependencies.