NAME
b
– build system driver
SYNOPSIS
b --help
b --version
b [options] [variables] [buildspec]
buildspec =
meta-operation(operation(target...[,parameters])...)...
DESCRIPTION
The build2
build system driver executes a set of
meta-operations on operations on targets according to the build
specification, or buildspec for short. This process can be
controlled by specifying driver options
and build system
variables
.
Note that options
, variables
, and
buildspec
fragments can be specified in any order. To
avoid treating an argument that starts with '-'
as an
option, add the '--'
separator. To avoid treating an
argument that contains '='
as a variable, add the second
'--'
separator.
All components in the buildspec can be omitted. If
meta-operation
is omitted, then it defaults to
perform
. If operation
is omitted,
then it defaults to the default operation for this meta-operation. For
perform
it is update
. Finally, if
target
is omitted, then it defaults to the current
working directory. A meta-operation on operation is called an action.
Some operations and meta-operations may take additional
parameters
. For example:
$ b # perform(update(./)) $ b foo/ # perform(update(foo/)) $ b foo/ bar/ # perform(update(foo/ bar/)) $ b update # perform(update(./)) $ b 'clean(../)' # perform(clean(../)) $ b perform # perform(update(./)) $ b configure # configure(?(./)) $ b 'configure(../)' # configure(?(../)) $ b clean update # perform(clean(./) update(./)) $ b configure update # configure(?(./)) perform(update(./)) $ b 'create(conf/, cxx)' # create(?(conf/), cxx)
Notice the question mark used to show the (imaginary) default operation
for the configure
meta-operation. For
configure
the default operation is "all operations".
That is, it will configure all the operations for the specified target.
You can also "generate" multiple operations for the same set of targets. Compare:
$ b 'clean(foo/ bar/)' 'update(foo/ bar/)' $ b '{clean update}(foo/ bar/)'
Some more useful buildspec examples:
$ b '{clean update}(...)' # rebuild $ b '{clean update clean}(...)' # make sure builds $ b '{clean test clean}(...)' # make sure passes tests $ b '{clean disfigure}(...)' # similar to distclean
In POSIX shells parenthesis are special characters and must be quoted when used in a buildspec. Besides being an inconvenience in itself, quoting also inhibits path auto-completion. To help with this situation a shortcut syntax is available for executing a single operation or meta-operation, for example:
$ b clean: foo/ bar/ # clean(foo/ bar/) $ b configure: src/@out/ # configure(src/@out/) $ b create: conf/, cxx # create(conf/, cxx) $ b configure: config.cxx=g++ src/ # configure(src/) config.cxx=g++
To activate the shortcut syntax the first buildspec argument must start
with an operation or meta-operation name and end with a colon
(:
). To transform the shortcut syntax to the normal
buildspec syntax the colon is replaced with the opening parenthesis
('(
'), the rest of the buildspec arguments are treated
as is, and the final closing parenthesis (')
') is
added.
For each target
the driver expects to find
buildfile
either in the target's directory or, if the
directory is part of the out
tree
(out_base
), in the corresponding src
directory (src_base
).
For example, assuming foo/
is the source directory of
a project:
$ b foo/ # out_base=src_base=foo/ $ b foo-out/ # out_base=foo-out/ src_base=foo/ $ b foo-out/exe{foo} # out_base=foo-out/ src_base=foo/
An exception to this requirement is a directory target in which case,
provided the directory has subdirectories, an implied
buildfile
with the following content is assumed:
# Implied directory buildfile: build all subdirectories. # ./: */
In the above example, we assumed that the build system driver was able to
determine the association between out_base
and
src_base
. In case src_base
and
out_base
are not the same directory, this is achieved in
one of two ways: the config
module (which implements the
configure
, disfigure
, and
create
meta-operations) saves this association as part
of the configuration process. If, however, the association hasn't been
saved, then we have to specify src_base
explicitly using
the following extended target
syntax:
src-base/@target
Continuing with the previous example:
$ b foo/@foo-out/exe{foo} # out_base=foo-out/ src_base=foo/
Normally, you would need to specify src_base
explicitly only once, during configuration. For example, a typical usage
would be:
$ b configure: foo/@foo-out/ # src_base is saved $ b foo-out/ # no need to specify src_base $ b clean: foo-out/exe{foo} # no need to specify src_base
Besides in and out of source builds, build2
also
supports configuring a project's source directory as forwarded to an
out of source build. With such a forwarded configuration in place, if we run
the build system driver from the source directory, it will automatically
build in the output directory and backlink (using symlinks or another
suitable mechanism) certain "interesting" targets (executables,
documentation, etc) to the source directory for easy access. Continuing with
the previous example:
$ b configure: foo/@foo-out/,forward # foo/ forwarded to foo-out/ $ cd foo/ $ b # build in foo-out/ $ ./foo # symlink to foo-out/foo
The ability to specify build2
variables as part of
the command line is normally used to pass configuration values, for
example:
$ b config.cxx=clang++ config.cxx.coptions=-O3
Similar to buildspec, POSIX shells often inhibit path auto-completion on the right hand side of a variable assignment. To help with this situation the assignment can be broken down into three separate command line arguments, for example:
$ b config.import.libhello = ../libhello/
The build system has the following built-in and pre-defined meta-operations:
perform
- Perform an operation.
configure
- Configure all operations supported by a project and save the result in
the project's
build/config.build
file. Implemented by theconfig
module. For example:$ b configure \ config.cxx=clang++ \ config.cxx.coptions=-O3 \ config.install.root=/usr/local \ config.install.root.sudo=sudo
Use the
forward
parameter to instead configure a source directory as forwarded to an out of source build. For example:$ b configure: src/@out/,forward
disfigure
- Disfigure all operations supported by a project and remove the project's
build/config.build
file. Implemented by theconfig
module.Use the
forward
parameter to instead disfigure forwarding of a source directory to an out of source build. For example:$ b disfigure: src/,forward
create
- Create and configure a configuration project. Implemented by the
config
module.Normally a
build2
project is created manually by writing thebootstrap.build
andconfig.build
files, adding source files, and so on. However, a special kind of project, which we call configuration, is often useful. Such a project doesn't have any source files of its own. Instead, it serves as an amalgamation for building other projects as part of it. Doing it this way has two major benefits: sub-projects automatically resolve their imports to other projects in the amalgamation and sub-projects inherits their configuration from the amalgamation (which means if we want to change something, we only need to do it in one place).As an example, let's assume we have two C++ projects: the
libhello
library inlibhello/
and thehello
executable that imports it inhello/
. And we want to buildhello
withclang++
.One way to do it would be to configure and build each project in its own directory, for example:
$ b configure: libhello/@libhello-clang/ config.cxx=clang++ $ b configure: hello/@hello-clang/ config.cxx=clang++ \ config.import.libhello=libhello-clang/
The two drawbacks, as mentioned above, are the need to explicitly resolve the import and having to make changes in multiple places should, for example, we want to switch from
clang++
tog++
.We can, however, achieve the same end result but without any of the drawbacks using the configuration project:
$ b create: clang/,cxx config.cxx=clang++ # Creates clang/. $ b configure: libhello/@clang/libhello/ $ b configure: hello/@clang/hello/
The targets passed to the
create
meta-operation must be directories which should either not exist or be empty. For each such directorycreate
first initializes a project as described below and then configures it by executing theconfigure
meta-operation.The first optional parameter to
create
is the list of modules to load inroot.build
. By default,create
appends.config
to the names of these modules so that only their configurations are loaded. You can override this behavior by specifying the period (.
) after the module name. You can also instructcreate
to use the optional module load by prefixing the module name with the question mark (?
).The second optional parameter is the list of modules to load in
bootstrap.build
. If not specified, then thetest
,dist
, andinstall
modules are loaded by default. Theconfig
module is always loaded first.Besides creating project's
bootstrap.build
androot.build
,create
also writes the rootbuildfile
with the following contents:./: {*/ -build/}
If used, this
buildfile
will build all the sub-projects currently present in the configuration. dist
- Prepare a distribution containing all files necessary to perform all
operations in a project. Implemented by the
dist
module. info
- Print basic information (name, version, source and output directories,
etc) about one or more projects to
stdout
, separating multiple projects with a blank line. Each project is identified by its root directory target. For example (some output is omitted):$ b info: libfoo/ libbar/ project: libfoo version: 1.0.0 src_root: /tmp/libfoo out_root: /tmp/libfoo subprojects: @tests project: libbar version: 2.0.0 src_root: /tmp/libbar out_root: /tmp/libbar-out subprojects: @tests
To omit discovering and printing subprojects information, use the
no_subprojects
parameter, for example:$ b info: libfoo/,no_subprojects
To instead print this information in the JSON format, use the
json
parameter, for example:$ b info: libfoo/,json
In this case the output is a JSON array of objects which are the serialized representation of the following C++
struct
project_info
:struct subproject { string path; optional<string> name; }; struct project_info { optional<string> project; optional<string> version; optional<string> summary; optional<string> url; string src_root; string out_root; optional<string> amalgamation; vector<subproject> subprojects; vector<string> operations; vector<string> meta_operations; vector<string> modules; };
For example:
[ { "project": "libfoo", "version": "1.0.0", "summary": "libfoo C++ library", "src_root": "/tmp/libfoo", "out_root": "/tmp/gcc-debug/libfoo", "amalgamation": "..", "subprojects": [ { "path": "tests" } ], "operations": [ "update", "clean", "test", "update-for-test", "install", "uninstall", "update-for-install" ], "meta-operations": [ "perform", "configure", "disfigure", "dist", "info" ], "modules": [ "version", "config", "test", "install", "dist" ] } ]
See the JSON OUTPUT section below for details on the overall properties of this format and the semantics of the
struct
serialization.
The build system has the following built-in and pre-defined operations:
update
- Update a target.
clean
- Clean a target.
test
- Test a target. Performs
update
as a pre-operation. Implemented by thetest
module. update-for-test
- Update a target for testing. This operation is equivalent to the
update
pre-operation as executed by thetest
operation and can be used to only update what is necessary for testing. Implemented by thetest
module. install
- Install a target. Performs
update
as a pre-operation. Implemented by theinstall
module. uninstall
- Uninstall a target. Performs
update
as a pre-operation. Implemented by theinstall
module. update-for-install
- Update a target for installation. This operation is equivalent to the
update
pre-operation as executed by theinstall
operation and can be used to only update what is necessary for installation. Implemented by theinstall
module.
Note that buildspec and command line variable values are treated as
buildfile
fragments and so can use quoting and escaping
as well as contain variable expansions and evaluation contexts. However, to
be more usable on various platforms, escaping in these two situations is
limited to the effective sequences of \'
,
\"
, \\
, \$
, and
\(
with all other sequences interpreted as is. Together
with double-quoting this is sufficient to represent any value. For
example:
$ b config.install.root=c:\projects\install $ b "config.install.root='c:\Program Files\test\'" $ b 'config.cxx.poptions=-DFOO_STR="foo"'
OPTIONS
DEFAULT OPTIONS FILES
Instead of having a separate config file format for tool configuration,
the build2
toolchain uses default options files
which contain the same options as what can be specified on the command line.
The default options files are like options files that one can specify with
--options-file
except that they are loaded by
default.
The default options files for the build system driver are called
b.options
and are searched for in the
.build2/
subdirectory of the home directory and in the
system directory (for example, /etc/build2/
) if
configured. Note that besides options these files can also contain global
variable overrides.
Once the search is complete, the files are loaded in the reverse order, that is, beginning from the system directory (if any), followed by the home directory, and finishing off with the options specified on the command line. In other words, the files are loaded from the more generic to the more specific with the command line options having the ability to override any values specified in the default options files.
If a default options file contains
--no-default-options
, then the search is stopped at the
directory containing this file and no outer files are loaded. If this option
is specified on the command line, then none of the default options files are
searched for or loaded.
An additional directory containing default options files can be specified
with --default-options
. Its configuration files are
loaded after the home directory.
The order in which default options files are loaded is traced at the
verbosity level 3 (-V
option) or higher.
JSON OUTPUT
Commands that support the JSON output specify their formats as a
serialized representation of a C++ struct
or an array
thereof. For example:
struct package { string name; }; struct configuration { uint64_t id; string path; optional<string> name; bool default; vector<package> packages; };
An example of the serialized JSON representation of
struct
configuration
:
{ "id": 1, "path": "/tmp/hello-gcc", "name": "gcc", "default": true, "packages": [ { "name": "hello" } ] }
This sections provides details on the overall properties of such formats
and the semantics of the struct
serialization.
The order of members in a JSON object is fixed as specified in the
corresponding struct
. While new members may be added in
the future (and should be ignored by older consumers), the semantics of the
existing members (including whether the top-level entry is an object or
array) may not change.
An object member is required unless its type is
optional<>
, bool
, or
vector<>
(array). For bool
members absent means false
. For
vector<>
members absent means empty. An empty
top-level array is always present.
For example, the following JSON text is a possible serialization of the
above struct
configuration
:
{ "id": 1, "path": "/tmp/hello-gcc" }
EXIT STATUS
Non-zero exit status is returned in case of an error.
ENVIRONMENT
The HOME
environment variable is used to determine
the user's home directory. If it is not set, then
getpwuid(3)
is used instead. This value is used to
shorten paths printed in diagnostics by replacing the home directory with
~/
. It is also made available to
buildfile
's as the build.home
variable.
The BUILD2_VAR_OVR
environment variable is used to
propagate global variable overrides to nested build system driver
invocations. Its value is a list of global variable assignments separated
with newlines.
The BUILD2_DEF_OPT
environment variable is used to
suppress loading of default options files in nested build system driver
invocations. Its values are false
or
0
to suppress and true
or
1
to load.
BUGS
Send bug reports to the users@build2.org mailing list.