After a long time passed without any BuildStream updates, I’m proud to finally announce that unstable BuildStream 2 development phase is coming to a close.
As of the 1.95.0 beta release, we have now made the promise to remain stable and refrain from introducing any more API breaking changes.
At this time, we are encouraging people to try migrating to the BuildStream 2 API and to inform us of any issues you have via our issue tracker.
Installing BuildStream 2
At this time we recommend installing BuildStream 2 into a python venv, this allows parallel installability with BuildStream 1 in the case that you may need both installed on the same system.
First you need to install BuildBox using these instructions, and then you can install BuildStream 2 from source following these commands:
# Install BuildStream 2 in a virtual environment cd buildstream git checkout 1.95.0 python3 -m venv ~/buildstream2 ~/buildstream2/bin/pip install . # Activate the virtual environment to use `bst` . ~/buildstream2/bin/activate
Porting projects to BuildStream 2
In order to assist in the effort of porting your projects, we have compiled a guide which should be helpful in updating your BuildStream YAML files.
The guide does not cover the python API. In case you have custom plugins which need to be ported to the new API, you can observe the API reference here and you are encouraged to reach out to us on our project mailing list where we will be eager to answer any questions and help out in the porting effort.
What’s new in BuildStream 2 ?
This would be a very exhaustive list, so I’ll try to summarize the main changes as succinctly as possible.
BuildStream now supports building remotely using the Remote Execution API (REAPI), which is a standard protocol used by various applications and services such as Bazel, recc, BuildGrid, BuildBarn and Buildfarm.
As the specification allows for variations in setup and implementation of remote execution clusters, there are some limitations on what can be used by BuildStream documented here.
Load time performance
In order to support large projects (in the 100,000 elements range), the loading codepaths have undergone a massive overhaul. Various recursive algorithms have been eliminated in favor of iterative ones, and cython is used for the hot code paths.
This makes large projects manageable, and noticeably improves performance and responsiveness on the command line.
Artifact and Source caching
BuildStream now uses implementations of the Content Addressable Storage (CAS) and Remote Asset services which are a part of the Remote Execution API exclusively to store artifacts and sources in remote caches. As such, we no longer ship our own custom implementation of an artifact server, and currently recommend using BuildBarn.
Supported implementations of cache servers are documented here.
In addition to caching and sharing built artifacts on artifact servers, BuildStream now also caches source code in CAS servers. This will imply an initial performance degradation on the initial build while BuildStream populates the caches but should improve performance under regular operation, assuming that you have persistent local caches, or have decent bandwidth between your build machines and CAS storage services.
On Linux build hosts, BuildBox will use a fuse filesystem to expose files in CAS directly to the containerized build environment. This results in some optimization of the build environment and also avoids the hard limit on hardlinks which we sometimes encounter with BuildStream 1.
BuildBox is also used for the worker implementation when building remotely using the BuildGrid remote execution cluster implementation.
Cache Key Stability
BuildStream 2 comes with a new promise to never inadvertently change artifact cache keys in future releases.
This is helpful to reduce unnecessary rebuilds and potential resulting validation of artifacts when upgrading BuildStream to new versions.
In the future, it is always possible that a new feature might require a change to the artifact content and format. Should such a scenario arise, our policy is to support the old format and make sure that new features which require artifact changes be opt-in.
Caching failed builds
With BuildStream 2, it is now possible to preserve and share the state of a failed build artifact.
This should be useful for local debugging of builds which have failed in CI or on another user’s machine.
YAML Format Enhancements
A variety of enhancements have been made to the YAML format:
- Variable expansion is now performed unconditionally on all YAML. This means it is now possible to use variable substitution when declaring sources as well as elements.
- The toplevel-root and project-root automatic variables have been added, allowing some additional flexibility for specifying sources which must be obtained in project relative locations on the build host.
- Element names are more clearly specified, and it is now possible to refer to elements across multiple junction/project boundaries, both on the command line and also as dependencies.
- It is now possible to override an element in a subproject, including the ability to override junction definitions in subprojects. This can be useful to resolve conflicts where multiple projects depend on the same junction (diamond shaped project dependency graphs). This can also be useful to override how a single element is built in a subproject, or cause subproject elements to depend on local dependencies.
- The core link element has been introduced, which simply acts as a symbolic link to another element in the same project or in a subproject.
- New errors are produced when loading multiple junctions to the same project, these errors can be explicitly avoided using the duplicates or internal keywords in your project.conf.
- ScriptElement and BuildElement implementations now support extended configuration in dependencies, allowing one to stage dependencies in alternative locations at build time.
- Loading pip plugins now supports versioning constraints, this offers a more reliable method for specifying what plugins your project depends on when loading plugins from pip packages installed in the host python environment.
- Plugins can now be loaded across project boundaries using the new junction plugin origin. This is now the recommended way to load plugins, and plugin packages such as buildstream-plugins are accessible using this method. An example of creating a junction to a plugin package and using plugins from that package is included in the porting guide.
New Plugin Locations
Plugins which used to be a part of the BuildStream core, along with some additional plugins, have been migrated to the buildstream-plugins repository. A list of migrated core plugins and their new homes can be found in the porting guide.
We’ve come a long way in the last years, and I’d like to thank:
- All of our contributors individually, whom are listed in our beta release announcement.
- Our downstream projects and users who have continued to have faith in the project.
- Our stakeholder Bloomberg, who funded a good portion of the 2.0 development, took us into the Remote Execution space and also organized the first Build Meetup events.
- Our stakeholder Codethink, who continues to support and fund the project since founding the BuildStream project in 2016, organized several hackfests over the years, organized the 2021 chapter of the Build Meetup during lockdowns, and has granted us the opportunity to tie up the loose ends and bring BuildStream 2.0 to fruition.