build2 0.4.0 Release Notes

These release notes provide a more detailed discussion of major new features in the build2 toolchain version 0.4.0, including motivation for implementing them and their usage examples. For the complete list of changes, see the Release Announcement or the NEWS files in the individual packages.

Build System

The build system has seen a lot of development with the NEWS file entries spanning over four pages. But the main feature is undoubtedly support for Windows.

The entire toolchain can now be built and used on Windows (XP and up) with either MSVC or MinGW GCC. With VC, the toolchain can be built with version 14 Update 2 or later and used with any version from 7.1. BTW, you can also build build2 with one compiler and use it with another (or even both) – there is nothing wrong with that.

To also arrive in this release is the new Installation and Upgrade manual for all the supported platforms and compilers.

Other major new features in this version include support for C compilation (with mixed C/C++ source building), pkg-config integration (with fixes for cross-compilation), initial support for library versioning, and support for the uninstall operation in addition to install.

This release also implements a more fleshed-out library dependency export model. In a nutshell, a library dependency on another library is either an interface or implementation. If it is an interface, then everyone who links this library should also be linking the interface dependency. A good example of an interface dependency is a library that is called in an inline function. In build2 you list interface dependencies of a library explicitly and the build system will take care of the rest.

There is also support for symbol exporting on Windows and build2 now does all the right things when linking static vs shared libraries with regards to which library dependencies to link (interface only for shared, both for static), which -rpath/-rpath-link options to pass, and so on.

To put it all together here is a buildfile for the libhello library from the Introduction:

import int_libs = libformat%lib{format}
import imp_libs = libprint%lib{print}

lib{hello}: {hxx cxx}{hello} hxx{export} $imp_libs $int_libs

# For pre-releases use the complete version to make sure they cannot
# be used in place of another pre-release or the final version.
#
if $abi_prerelease
  lib{hello}: bin.lib.version = @-$version
else
  lib{hello}: bin.lib.version = @-$abi_major.$abi_minor

cxx.poptions =+ -I$src_root
obja{*}: cxx.poptions += -DLIBHELLO_STATIC_BUILD
objs{*}: cxx.poptions += -DLIBHELLO_SHARED_BUILD

lib{hello}: cxx.export.poptions = -I$src_root
liba{hello}: cxx.export.poptions += -DLIBHELLO_STATIC
libs{hello}: cxx.export.poptions += -DLIBHELLO_SHARED

lib{hello}: cxx.export.libs = $int_libs

# Install into the hello/ subdirectory of, say, /usr/include/.
#
install.include = $install.include/hello/

Package Manager

The two major new features in bpkg are support for repository signing and system packages.

The purpose of signing a repository is to prevent tampering with packages either during transmission or on the repository host machine. bpkg uses X.509 public key cryptography for repository signing. Currently, only the explicit first use certificate authentication is implemented (similar to ssh) but a CA-based model may be added in the future.

In a nutshell, repository signing involves three steps: First you create a private key/certificate pair and copy the certificate to the repository manifest. Then, when re-generating the repository packages manifest with the bpkg-rep-create(1) command, you specify the location of the private key with the --key option. Finally, when a user tries to fetch a signed repository for the first time, they will see a prompt along these lines:

warning: authenticity of the certificate for repository
  build2.org/hello/stable cannot be established
certificate is for build2.org, "Code Synthesis" <admin@build2.org>
certificate SHA256 fingerprint:
FF:DF:7D:38:67:4E:C3:82:[...]:30:56:B9:77:B9:F2:01:94
trust this certificate? [y/N]

One can further improve on this by storing the private key in a PIV/PKCS#11 device such as Yubikey. That's what we do for all the repositories hosted on build2.org and cppget.org. For more information on repository signing see the bpkg-repository-signing(1) help topic.

The other major new feature in bpkg is support for system packages. Often you have certain packages installed system-wide, using your distribution's package manager and you would like your builds to use that instead of bpkg fetching its source code and building it from scratch.

To support this a package can now be "built" as available from the system rather than compiling it from source. To specify a system package we use the new sys: package scheme, for example:

bpkg build sys:libsqlite3

Currently, if no version is specified for a system package, then it is considered to be unknown but satisfying any dependency constraint (such a wildcard version is displayed as *). In the future we plan to support querying system package managers (rpm, dpkg, pkg-config) for the installed version and perhaps even automatically discovering if a system-installed version is available. For more details on system packages see the bpkg-pkg-build(1) command documentation.

Repository Web Interface

To support repository signing, brep now displays the repository certificate information (subject, fingerprint) and the certificate itself on the repository about page.

However, the most significant user-visible change in brep is probably the packaging of all its prerequisites (ODB libraries, libstudxml, libapr1, libpq; except for the Apache2 headers). As a result, one can now build brep on UNIX-like operating systems with a single line like this:

$ bpkg build brep ?sys:libapr1 ?sys:libpq