Building a C++ package with rattler-build
Conda packages are not only for Python! In fact, one of the strong points of conda packages (and why we are betting on them) is that they are completely language agnostic. This means that you can ship your software in a conda-package, whether it is written in Python, C++ or C, Rust, Zig, or any other language.
In this blog post, we will show you how to build a C++ package with conda-forge
and the new rattler-build
tool. rattler-build
is a tool that reads a
"recipe" file and then creates a package from the recipe. It is a modern
replacement for the old conda-build
tool, and it is much faster and easier to
use.
What is a recipe?
A recipe is a YAML file that contains the instructions for the build. It usually contains the following sections:
- package: This section contains the name and the version of the package
- source: This section contains the URL to the source code and a checksum (SHA256 or MD5).
- build: This section contains the instructions to build the package and some additional configuration options.
- tests: This section contains the instructions to run the tests after the package has been built.
- about: This section contains the metadata about the package, such as the description, the license, and the home page.
Let's build a package
There are some hot new C++ libraries out there. One that I have personally worked on is called "xtensor". It is a C++ library for numerical computing with multi-dimensional arrays which implements many of the ideas of NumPy in C++. Since it is a header-only library the build process is also pretty quick.
Here is a recipe for building the xtensor package:
Let's go through the recipe step by step:
- The
context
section contains the name and the version of the package. These are used to fill in the variables in the rest of the recipe. - The
package
section contains the name and the version of the package. These will be used if other packages depend on this package (as input to the SAT solver) and if you use the package in apixi.toml
file. - The
source
section contains the URL to the source code and a checksum (SHA256 or MD5). This is used to download the source code and to verify that it has not been tampered with. - The
build
section contains the instructions to build the package and some additional configuration options. In this case, we usecmake
to build the package andninja
to run the build. We also set some CMake variables to configure the build. The main trick is that we install the files into the$PREFIX
(or%LIBRARY_PREFIX%
on Windows) directory. Any files that are added during the build process to the$PREFIX
directory will be included in the package. - The
requirements
section contains the list of dependencies that are needed to build the package. In this case, we need a C++ compiler,cmake
, andninja
. We also need thextl
andxsimd
libraries to run the package. We use a special Jinja function for thecompiler
requirement, which will automatically select the right compiler for thetarget_platform
(this also works for cross-compilation). - The
tests
section contains the instructions to run the tests after the package has been built. In this case, we check that the package contains the right files by using apackage_contents
test. You can also write tests that run a script and execute any binaries that are included in the package. - The
about
section contains the metadata about the package, such as the description, the license, and the home page. This is used to display informative metadata in the repository.
Building the package
To build this package, you need rattler-build
. The easiest way to get
rattler-build
on your system is of course with pixi:
Will make the rattler-build
command globally available on your system.
Once installed you can execute the build with the following command:
This will place the new package into the
~/bld-folder/osx-arm64/<package>.tar.bz2
folder. Note that the package will be
built for your current platform, so if you are running Linux or Windows, the
folder will be win-64
or linux-64
etc.
Using the package from a local source in pixi
To use the package from the local build folder in pixi you just need to point
the pixi.toml
to that folder:
This will make pixi install the package from the local folder instead of the conda-forge repository (any run dependencies of xtensor will still come from conda-forge, though).
With pixi you will get all the same benefits of reproducibility and lock files to build your own C++ projects on top.
Automate your package building
To build your packages for multiple platforms you can use the new rattler-build-action Github Action
(or just use rattler-build
on your preferred CI provider).
After the packages are built, you can upload them to your own package server or a channel on prefix.dev (you can choose between private and public channels). To learn more about channels on prefix, read this blog post.
Read more
If you want to learn more about rattler-build
and how to use it, you can check
the rattler-build
documentation. To get inspiration
on how to write recipes, you can check the conda-forge documentation or the
conda-forge feedstock repositories on GitHub. They currently use the old format
(meta.yaml
) that is used by conda-build
but for most recipes it is pretty
straightforward to convert them to the new format. We are in the process of
adding support for rattler-build
and the new recipe format to conda-forge, so
be excited for the future!