BUILD SYSTEMS AND PACKAGE MANAGERS

# A C/C++ Build System/Package Manager Comparison

## Overview

This article is a opinionated comparison of popular, open-source build systems/package managers for C/C++. This review looks at both programs that compile your code and those that manage dependencies, as the line between build systems and package managers is blurred. The build and packaging support are treated as separate qualities which will be reviewed for each.

The build systems are listed in alphabetical order.

The GitHub repository mbedded-ninja/CppBuildSystemReview contains a example/demo project for each build/packaging system mentioned below (one per folder). In each folder, there is a build.sh bash script which should automatically run the build on a Linux system, provided you have the build system installed.

## The Opinionated TL;DR

If you want a full end-to-end package manager and build system setup, have a look at Conan with CMake. If you just are after a modern, powerful build system for typical build situations, have a look at Bazel. If you are thinking about cross-compiling (e.g. embedded targets), want something mature and well-known, or have a complicated build structure, have a look at CMake by it’s own.

If you are thinking of using Scons or Makefiles, please make sure you are doing so for a good reason! Perhaps it’s because it has to integrate with a system that already uses these tools, or that is what your company prefers. If you are considering it for a completely new project, I strongly recommend you consider some of the alternatives!

## Bazel

 Build Functionality 9/10 Bazel is great a building C/C++ packages. Package Functionality 7/10 Bazel does have support for packages, in the sense that projects can depend on targets from other parts of the filesystem or from the internet. Bazel will automatically download dependencies as needed. One disappointment is there is no install functionality. Platform Support 7/10 Although Linux, macOS and Windows are all supported, I have seen reports of slow build times in macOS and Windows. Usability 6/10 Bazel has a clean and simple syntax, using WORKSPACE and BUILD files [written in Skylark](https://blog.bazel.build/2017/03/21/design-of-skylark.html), a language very similar to Python. Bazel loses a few points here for the extra complexity when cross-compiling (although when is cross-compiling ever easy!). Scalability/Speed 8/10 Although never tested myself, Bazel claims to cache data, optimize the dependency analysis and perform parallel execution on the builds. And it's used by Google to undertake huge build processes, so it's guaranteed to be fast! Community 7/10 The Bazel community is strong, but is still young compared to other build systems (e.g. make, CMake). TOTAL 7/10

Bazel has some decent package manager support in the form of external dependencies. Bazel supports other local Bazel repositories, non-Bazel projects, and remote repositories which can be automatically downloaded by Bazel.

Cross-compilation using Bazel can be difficult (see https://github.com/bazelbuild/bazel/wiki/Building-with-a-custom-toolchain for reasons why).

As far as I’m aware, Bazel does not have the install functionality that build systems such as make and CMake have. The is no way to “install” the build executables, libraries and header files onto the system, be it the typically install locations (such as /usr/local/bin, /usr/local/lib, e.t.c. on Linux) or a custom install directory.

Bazel seems to have first tier build support for C/C++, Java, Android and iOS.

## Buck

 Build Functionality 10/10 After all, Buck is marketed as a build system! Package Functionality 6/10 Buck does not support the downloading of pre-built binary assets, everything must be built from source. However, Buck seems to have good support for locally built dependencies. Platform Support 7/10 (Linux, macOS, Windows). Buck can be tricky to install on Windows and Linux (well supported on macOS via homebrew). Usability 8/10 Buck is very easy to configure for both building and packaging C/C++ libraries/applications. Scalability/Speed 9/10 Buck is designed to be fast. It even attempts to work out what dependency headers to use, and only recompile if these change. Going hand-in-hand with Buck speed, it was designed from the start to be highly scalable. Community 6/10 Although the documentation is quite comprehensive, Buck is still young at it can be difficult to find solutions to problems on places such as StackOverflow. It does have over 5.5k stars on GitHub! TOTAL 7/10 A relatively new, cross-platform, multi-language build system that has a promising future.

## Buckaroo

Buckaroo is a package manager that uses Buck as the build system.

Unfortunately, I do not believe that Buckaroo supports local dependencies. All dependencies have to come from

## CMake

 Build Functionality 9/10 CMake is mature and has a very complete feature set. Package Functionality 6/10 Platform Support 9/10 (Linux, macOS, Windows). One of CMake's core qualities is to be platform and build system independent! Usability 5/10 CMake can be somewhat easy to use for a self-contained build, but can get rather complex when dealing with dependencies (exporting, supporting find_package, .cmake.in files, e.t.c, see here. Scalability/Speed 7/10 CMake supports large, multi-dependency projects well. However, you can get into a bit of a mess if proper "best practises" are not followed. Community 8/10 CMake has become the defacto standard for newer C++/C projects. TOTAL 7/10 Definitely a build system I would recommend!

CMake is a C/C++ build system which strives to be operating system and compiler independent. CMake itself does not actually run the build process, instead, it generates build files for another build system, which is typically make on UNIX systems and Visual Studio on Windows systems.

CMake is driven by scripts in CMakeLists.txt files, usually contained in the root and relevant sub-directories directories of the project you are building. The language of a CMakeLists.txt file may seem a little foreign at first but is a powerful way of expressing the build process.

The default way of building a CMake project usually looks something like:

ProjectDir$mkdir build ProjectDir$ cd build
ProjectDir/build$cmake .. ProjectDir/build$ make


There is an interesting Hunter package manager which is aimed at making CMake package management easier. I decided not to include Hunter as a separate build system because of the similarities, but it definitely shows promise when it comes to making CMake easier to use!

For more information on CMake, see the dedicated CMake section of mbedded.ninja.

## Conan

 Build Functionality 7/10 Although Conan is marketed as a package manager, it has first-tier integration with build systems such as CMake, and can even call/perform the build for you. Package Functionality 9/10 Conan is first and foremost a package manager, so it ranks highly here. Platform Support 9/10 (Linux, macOS, Windows). Written in python, it is supported on all popular platforms. When choosing CMake as the build system (this seems to be the popular option), this cross-platform support continues. Usability 7/10 Scalability/Speed 7/10 Given Conan's first-tier binary package support, compilation should be fast on common platforms as you won't be building from source. Community 8/10 With over 1.6k stars on GitHub, and fairly comprehensive documentation, Conan has a large number of users (although Buck has more). TOTAL 8/10

Conan is solely a C/C++ package manager, although it provides interfaces to common build tools such as CMake (this seems to be popular pairing). Installation can be as simple as \$ pip install conan.

Conan is tightly integrated with official and community repositories which house popular packages. The official repository is on bintray. It also uses a local repository (or cache) which is used to prevent multiple copies of the same dependency, and for local/private package development.

When used with CMake, Conan can take over the responsibility of what is traditionally CMake’s install/export steps. The install/export steps have always been a difficult issue with CMake, which requires complex logic to produce a relocatable, re-usable upstream CMake package.

## Makefiles

 Build Functionality 6/10 Package Functionality 3/10 Make supporting packages? Hahahaha... Platform Support 10/10 (Linux, macOS, Windows, ...). Makefiles have been around since the dawn of time, and are supported almost everywhere! Usability 1/10 Ever tried to write a Makefile by hand? If you have, you will appreciate this score. Scalability/Speed 2/10 Community 8/10 Makefiles, being one of the oldest build systems still in popular use, has plenty of online resources! TOTAL 3/10

No. No. No. Please don’t consider raw makefiles as your build system unless you absolutely have to. Did I mention this comparison was opinionated?

## Scons

 Build Functionality 6/10 Package Functionality 1/10 SCons doesn't really have any package management features. Platform Support 8/10 Usability 4/10 Scalability/Speed Community 3/10 TOTAL 4/10

SCons is a build tool, with no real package management features. The technical limitations of SCons starts to make the scripts complex when it comes to local builds with multiple dependencies and local install paths.

## Examples

I tried to do the following for each build system:

• Compile source code into a executable