Professional CMake:

A Practical Guide

Learn to use CMake effectively with practical advice from a CMake co-maintainer. You can also have the author work directly with your team!

Enhanced source file handling with target_sources()

Updated December 2018: Parts of this article have been reworked to account for improvements made with the CMake 3.13.0 release. Key updates are noted within the article.

In all but trivial CMake projects, it is common to find targets built from a large number of source files. These files may be distributed across various subdirectories, which may themselves be nested multiple levels deep. In such projects, traditional approaches usually either list all source files at the top-most level or build up the list of source files in a variable and pass that to add_library(), add_executable(), etc. With CMake 3.1, a new command target_sources() was introduced which provides the missing piece among the various target_... commands. While the CMake documentation succintly describes what target_sources() does, it fails to highlight just how useful the new command is and why it promotes better CMake projects:

  • It can lead to cleaner and more concise CMakeLists.txt project files.
  • Dependency information can be specified closer to where the actual dependencies exist in the directory hierarchy.
  • Source files gain the ability to become part of a target’s interface.
  • Source files can be added to third party project targets without having to modify the third party project files.

Read more

Creating shortcuts with parameters using CMake/CPack and NSIS

CMake/CPack does a pretty good job of making it relatively easy to create a basic Windows installer. Sometimes, however, it trips you up when you want to do something seemingly common. One such example is creating Start Menu shortcuts for an executable where you also want to pass it some command line arguments. Surprisingly, CMake/CPack doesn’t give you a simple or generic way to do this. It provides very basic functionality via the CPACK_PACKAGE_EXECUTABLES variable in the CPack module, but that’s just a simple mapping of executable to menu shortcut name with no opportunity to provide command line arguments.

Read more

Building GoogleTest and GoogleMock directly in a CMake project

UPDATED December 2015:
Since the original article was written, gtest and gmock have been merged and moved into a single repository on Github under the name GoogleTest. I’ve updated the content here to reflect the changes and the article now also covers both gtest and gmock. I’ve also revised the general purpose implementation to make it more flexible, expanded its documentation and made it available on Github under a MIT license. I hope you find it useful.

UPDATED September 2019:
The generalised implementation was extended further and became the FetchContent module, which was added to CMake in 3.11. The module documentation uses GoogleTest in some of its examples.


Using gtest/gmock with CMake is awesome. Not so awesome is when you don’t have a pre-built gtest/gmock available to use. This article demonstrates a convenient way to add them with automated source download and have them build directly as part of your project using add_subdirectory(). Unlike other common approaches, no manual information has to be provided other than the package to download. The approach is general enough to be applied to any CMake-based external project, not just gtest/gmock.

Read more

Handling binary assets and test data with CMake

A common situation facing many projects is how to incorporate large binary assets into the main source code and its build process. Examples of such assets include firmware binaries for embedded products, videos, user manuals, test data and so on. These binary assets often have their own workflow for managing source materials, change history and building the binaries. This article demonstrates an approach to handling this situation with CMake builds.

Read more

Enabling C++11 And Later In CMake

Updated June 2020

With the constant evolution of C++, build systems have had to deal with the complication of selecting the relevant compiler and linker flags. If your project targets multiple platforms and compilers, this can be a headache to set up. Happily, with features added in CMake 3.1, it is trivial to handle this in a generic way.

Read more

CMake targets with detailed dependencies

If only software build systems would do what we intuitively expect! I’m sure many of you have your own horror stories of having to unravel convoluted scripts, project settings, compiler bugs, etc. in order to get code to build, despite the project requirements seeming to be relatively simple. If you work with cross-platform software, this is probably a pain point you are particularly familiar with. This article demonstrates some more recent features of CMake which greatly reduce that pain.

Read more