BUILD SYSTEMS AND PACKAGE MANAGERS

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

Date Published:
Last Modified:

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 Functionality9/10Bazel is great a building C/C++ packages.
Package Functionality7/10Bazel 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 Support7/10Although Linux, macOS and Windows are all supported, I have seen reports of slow build times in macOS and Windows.
Usability6/10Bazel 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/Speed8/10Although 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!
Community7/10The Bazel community is strong, but is still young compared to other build systems (e.g. make, CMake).
TOTAL7/10

Bazel is developed by Google.

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 Functionality10/10After all, Buck is marketed as a build system!
Package Functionality6/10Buck 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 Support7/10(Linux, macOS, Windows). Buck can be tricky to install on Windows and Linux (well supported on macOS via homebrew).
Usability8/10Buck is very easy to configure for both building and packaging C/C++ libraries/applications.
Scalability/Speed9/10Buck 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.
Community6/10Although 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!
TOTAL7/10A 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 Functionality9/10CMake is mature and has a very complete feature set.
Package Functionality6/10
Platform Support9/10(Linux, macOS, Windows). One of CMake's core qualities is to be platform and build system independent!
Usability5/10CMake 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/Speed7/10CMake supports large, multi-dependency projects well. However, you can get into a bit of a mess if proper "best practises" are not followed.
Community8/10CMake has become the defacto standard for newer C++/C projects.
TOTAL7/10Definitely 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 Functionality7/10Although 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 Functionality9/10Conan is first and foremost a package manager, so it ranks highly here.
Platform Support9/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.
Usability7/10
Scalability/Speed7/10Given Conan's first-tier binary package support, compilation should be fast on common platforms as you won't be building from source.
Community8/10With over 1.6k stars on GitHub, and fairly comprehensive documentation, Conan has a large number of users (although Buck has more).
TOTAL8/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 Functionality6/10
Package Functionality3/10Make supporting packages? Hahahaha...
Platform Support10/10(Linux, macOS, Windows, ...). Makefiles have been around since the dawn of time, and are supported almost everywhere!
Usability1/10Ever tried to write a Makefile by hand? If you have, you will appreciate this score.
Scalability/Speed2/10
Community8/10Makefiles, being one of the oldest build systems still in popular use, has plenty of online resources!
TOTAL3/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 Functionality6/10
Package Functionality1/10SCons doesn't really have any package management features.
Platform Support8/10
Usability4/10
Scalability/Speed
Community3/10
TOTAL4/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
  • Link a third-party library
  • Install static library (lib file and headers) and executable onto system
  • Run the executable to make sure it works

The minimal code for each platform to do the above can be found at https://github.com/gbmhunter/CppBuildSystemReview.

Each sub-directory contains an example for each build system. Each of these sub-directories also contains a bash script you can run for a one-click demo of the build and run process (have a look at the build script to see how it’s done!).


Like this page? Upvote with shurikens!

Tags:

    comments powered by Disqus