Use of CMake at Canonical
Canonical is most known for Ubuntu, which is the most popular desktop Linux distribution in the world. Its main product is very different than most software and solution vendors. Consequently, the way software is created at Canonical is quite unusual.
Rather than having one or a few grand source trees, Canonical has many individual projects. These projects are combined into a cohesive whole using standard Debian packaging tools. Another uncommon thing is that most employees work from home and come from every corner of the world. It is normal in a development team of five people to have participants from two or three different continents. Teams are given a rather large degree of autonomy regarding how they organize and implement their work items, as long as they stay within certain agreed upon limits. While this is great for initial development efficiency, it may cause friction when people move between projects because the tools vary between them.
In regards to build systems, most of Canonical’s projects previously used GNU Autotools. Some of the newer ones, however, used CMake and a few Qt applications used qmake. Build system selection was usually based on the very simple algorithm of going with the one with which the project initiator was most familiar.
The Race to Standardization
In late spring of 2012, Canonical started to really focus on bringing Ubuntu to phones. One major infrastructure piece in this puzzle was the Mir Display Server. When the project started, for possibly the first time, there was an actual debate about what build system to use. Eventually, CMake was chosen due to its flexibility and good cross compilation support.
It should be noted that Canonical’s use of CMake is again slightly different than with most corporate entities. With such entities, the choice is driven by CMake’s multi-platform support, especially for certain non-POSIX operating systems from the northwestern United States that seem to be quite popular on the desktop. Canonical’s projects are, almost without exception, designed to be Linux only. Even in this single-platform case, CMake was deemed to provide a better developer experience than its competition.
Positive results from Ubuntu and a few other projects eventually led to the decision to make CMake the standardized build system across all Canonical projects. Given earlier discussions on the issue, this was expected to raise some objections from people whose experiences were mostly with other build systems. Once the decision was made, the actual transition occurred with little opposition.
Currently, CMake is the standard build system for all projects at Canonical. There are still some old projects that use other build systems. However, a gentle and loving but continuously increasing pressure is being applied to them to transition. This process is expected to be finalized within a few months.
Problems encountered and lessons learned
The single biggest selling point of CMake to people accustomed to other build systems was something no one ever expected. It turned out to be the Ninja backend. Unix developers have used Make for so long that they have become accustomed to its disadvantages. One of these disadvantages is that Make is actually quite slow. That is not to say that any single implementation of Make is slow, but rather that Make as a system is slow. The reasons for this are varied and interesting, but they basically boil down to certain design decisions that turn out to be impossible to implement efficiently.
If you have even a moderate sized code base, Make can take tens of seconds just to determine that the build is up-to-date and that nothing needs to be done. Ninja can determine the same in a fraction of a second. Showing this to developers made them immediately see the benefits of transitioning to CMake. Many of them have since expressed severe dissatisfaction when they have had to work on any projects that do not have a Ninja backend.
Like any large-scale project, this transition also had some negative points. The main one had to do with CMake modules, rather than the core system itself. One of the main advantages of GNU Autotools is that it has a massive third-party library of code that can be used to do almost anything imaginable. CMake’s modules do not provide as much functionality, and the quality of some portions could be better.
Because Ubuntu is a global project, localization of software is extremely important. Internationalization is usually done with the GNU Gettext software package. CMake does provide a module for Gettext, but it has turned out to be confusing to use. People encountering it for the first time have, almost without exception, asked for help in using it. Some Autotools proponents even raised this as an issue serious enough to revert back to Autotools. Eventually, these problems were dealt with, and there have been few issues since then.
Another issue that was raised had to do with CMake’s language syntax. While expressing basic build setup was considered straightforward, coding new functionality was deemed trickier than necessary. Fortunately, most build issues have been solvable with the core modules that come with CMake.
Overall, the transition has been successful. While there has been no formal evaluation of how the transition has changed developer productivity, informal discussions seem to indicate that after the initial adjustment period, most people feel at home and enjoy the benefits provided by Ninja and other nice features offered by CMake.
A screenshot of a prototype version of Ubuntu phone running the Unity 8 shell on top of the Mir display server, both built with CMake
Jussi Pakkanen received his Ph.D in Computer Science in 2006. He currently works for Canonical, where he is colloquially known as that guy you should talk to if you have CMake questions. He has worked on projects such as the multi-touch framework, the Libcolumbus fuzzy matching library, Mediascanner, and Unity Scopes. He has also written his own build system called Meson, which is available at https://sourceforge.net/projects/meson/.