CMake is one of those utilities that has become virtually ubiquitous in the Open Source world. For those who don’t know what it does, it is most well known as a program for building the files needed to build projects – Make files, Ninja build files, Visual Studio solution files, etc. As this book shows, it can also do a lot more, but we will get to that later.
My previous experience with CMake has been almost entirely limited to editing existing config files that it reads to do its work, adding new source files or new compiler options as required.
Anything more advanced than that, like creating config files from scratch, has been limited by a lack of decent tutorial documentation available on-line. There is a lot of documentation out there, but it has always to be more aimed at people who are already familiar with CMake. This book fills that gap, providing a good introduction to setting up a project using CMake.
The book is divided into twelve chapters and an appendix, and it seems like a logical route to take to explain what each chapter does in turn.
Chapter 1, ‘First Steps With CMake’, starts off by giving a brief description of the steps CMake takes to generate the build files. It then explains how to install CMake on various OSes, if you don’t already have it installed. An introduction to the CMake command line follows, including mentioning why out-of-source builds are preferred and the first brief mentions of CTest and CPack. It then describes the various files that CMake uses to do its work, explaining what they do. Finally there is a brief description of CMake scripts and modules.
Chapter 2, ‘The CMake Language’, as its name implies, is an introduction to the CMake language, covering all the main details of it. There should be nothing in here to worry anyone with experience of programming or shell scripting languages.
Chapter 3, ‘Setting Up Your First CMake Project’, again as its name implies is an introduction to setting up a project to use CMake. It starts with the minimum set of commands that you CMake files should include, and setting up various project metadata. Then it describes how to partition up your project and suggests a directory structure to use. Finally it describes how to query the environment and configuring the toolchain used by your project.
Chapter 4, ‘Working With Targets’, describes how targets are handled in CMake. It includes basic information on what a target is, how to control the properties of targets, and also a useful discussion of how properties are propagated from a source target to a destination target. It then describes pseudo targets and build targets, before talking about custom commands and how they can be used for custom behaviour of targets. Finally it goes into detail on generator expressions and how they are used.
Chapter 5, ‘Compiling C++ Sources With CMake’, starts off with a discussion of the various stages a compiler goes through to actually do the compilation of source code. It then briefly mentions the commands CMake uses to affect each stage and to check that the compiler provides the facilities required, such as supporting the required version of the C++ standard. It then describes various kinds of optimization that compilers can carry out and how CMake allows you to control them. It also talks about enabling pre-compiled headers or unity builds for speeding up compilations.
Chapter 6, ‘Linking With CMake’, starts off with a description of what a linker does and why it is required. It then describes how CMake allows you to specify if a library will be built as a static or a shared library. There is then a more general discussion of various factors to do with linking which is only tangentially related to CMake.
Chapter 7, ‘Managing Dependencies With CMake’, is all about external dependencies of your project. In other words, what to do if your project requires something like the Google Protobuf Compiler to be built, rather than saying that file.cpp depends on file.h to build. It describes the facilities CMake provides to look for such external dependencies and pull them in if they are not present, such as downloading them from GitHub, or else give an error to the user saying they need to be installed.
Chapter 8, ‘Testing Frameworks’, describes using CMake to automate testing. A lot of this is related to using the CTest command to run the tests, and it starts off describing how you can write unit tests and have them recognised by CTest. It then briefly describes two testing frameworks, Catch2 and GTest/GMock, and how they can be hooked into CTest. Finally it talks about generating test coverage reports so you can check your tests are exercising your code fully.
Chapter 9, ‘Program Analysis Tools’, is all about using various program analysis tools and how to use them from CMake. It starts of with a brief description of clang-format, and then moves on to talking about various static analysis tools such as clang-tidy, Cpplint, and Cppcheck. It ends with a discussion on Valgrind’s Memcheck tool and how to use run it with your unit tests.
Chapter 10, ‘Generating Documentation’, is a short chapter which talks primarily about adding Doxygen comments to your source code and having it run automatically from CMake.
Chapter 11, ‘Installing And Packaging’, talks about how to install a project using CMake so that other projects on a system can discover it, and also about using the CPack tool to create a package for installation. The emphasis here is very much on using CMake to do the work, including having users of the package run CMake or CPack to actually handle the installation.
Chapter 12, ‘Creating Your Professional Project’, takes you through a very simple project to illustrate how the work described in the previous chapters comes together for a complete project.
Appendix, ‘Miscellaneous Commands’, describes in limited detail the
math() commands. This is really just a brief introduction to the various options (called modes) that each command offers. You would need to look at the online documentation for a more detailed description, but at least this shows what is available.
There are some niggles to the book, as there always will be. The emphasis on using CMake and related tools to do everything, including things like testing and packaging, might irritate some people, but is understandable given the book is about CMake. Also, some of the grammar is a little confusing, and there are places where it is looks like the technical proofing has gone a bit awry, but nothing that is actually wrong or misleading from what I can tell.
Overall, though, I found the book both informative and useful. It is a better introduction to using CMake than any I’ve found online so far, including the official CMake documentation. I certainly feel more confident in using CMake in my own projects now.