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.buildfile. Implemented by theconfigmodule. For example:$ b configure \ config.cxx=clang++ \ config.cxx.coptions=-O3 \ config.install.root=/usr/local \ config.install.root.sudo=sudoUse the
forwardparameter 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.buildfile. Implemented by theconfigmodule.Use the
forwardparameter 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
configmodule.Normally a
build2project is created manually by writing thebootstrap.buildandconfig.buildfiles, 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
libhellolibrary inlibhello/and thehelloexecutable that imports it inhello/. And we want to buildhellowithclang++.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
createmeta-operation must be directories which should either not exist or be empty. For each such directorycreatefirst initializes a project as described below and then configures it by executing theconfiguremeta-operation.The first optional parameter to
createis the list of modules to load inroot.build. By default,createappends.configto 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 instructcreateto 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, andinstallmodules are loaded by default. Theconfigmodule is always loaded first.Besides creating project's
bootstrap.buildandroot.build,createalso writes the rootbuildfilewith the following contents:./: {*/ -build/}If used, this
buildfilewill 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
distmodule. 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_subprojectsparameter, for example:$ b info: libfoo/,no_subprojects
To instead print this information in the JSON format, use the
jsonparameter, 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++
structproject_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
structserialization.
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
updateas a pre-operation. Implemented by thetestmodule. update-for-test- Update a target for testing. This operation is equivalent to the
updatepre-operation as executed by thetestoperation and can be used to only update what is necessary for testing. Implemented by thetestmodule. install- Install a target. Performs
updateas a pre-operation. Implemented by theinstallmodule. uninstall- Uninstall a target. Performs
updateas a pre-operation. Implemented by theinstallmodule. update-for-install- Update a target for installation. This operation is equivalent to the
updatepre-operation as executed by theinstalloperation and can be used to only update what is necessary for installation. Implemented by theinstallmodule.
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.