Hello CMake
Prerequisites:
This post assumes you are familiar with:
- C/C++
- at least one C/C++ build tool, system, or IDE (gcc/g++, gnu make, xcode, visual studio, etc)
Installing CMake
Instructions available: here
Installers available: here
What is CMake?
According to the CMake project (emphasis mine):
CMake is an open-source, cross-platform family of tools designed to build, test and package software. CMake is used to control the software compilation process using simple platform and compiler independent configuration files, and generate native makefiles and workspaces that can be used in the compiler environment of your choice.
-- cmake.org , December 2020
In short, CMake helps you manage the build configuration for portable C/C++ software projects.
Motivation for CMake
For maintainers / contributors of software projects:
If you want to write code that can be used on multiple platforms (Mac, Linux, Windows, etc), one option is to provide a build configuration for every platform you want to support:
- Makefile for GNU/Linux
- Xcode workspace for Mac
- Visual Studio solution for windows
If you're unfamiliar with the particulars of every platform, it might be impossible for you to support all of them. Even if you are familiar with all of these tools, over time you'll find yourself replicating small changes in build configurations across the multiple platforms, not to mention the inevitable drift between platforms 😬. You also can't see the future. What platforms and tools might exist 5 years from now?
For consumers / users of software projects:
Even more commmonly, if you want to reuse code that someone else has written you'd better hope they have also written a build configuration that supports your platform and tools of choice. Otherwise, you're in for a wild ride trying to piece together your own build from scratch.
That's where CMake come in — you can target (nearly) every platform and (nearly) every toolset, even ones that don't exist yet, with a single unified build configuration written in CMake. And for consumers it's consistent. You don't have to decipher eleventy dozen ad-hoc attempts at multi-platform build support.
Example 0: The Anatomy of a CMake Project
We'll start with the simplest possible project, containing just two files:
main.cpp
– the source code for a simple command line executableCMakeLists.txt
– a CMake build configuration
The source for this example is available as a GitHub gist. Let's take a closer look.
The source file, main.cpp
, contains exactly what you might expect from a hello, world
program.
The more interesting part here is the CMake build configuration, contained in CMakeLists.txt
.
In this case, there are exactly 3 lines of configuration:
- line 1:
cmake_minimum_required(VERSION 3.15)
- Every CMake build configuration should start with a minimum required version. When in doubt, use the current version number of your CMake executable (
cmake --version
)
- Every CMake build configuration should start with a minimum required version. When in doubt, use the current version number of your CMake executable (
- line 2:
project(HelloCMake)
- This tells CMake you are defining a new project named
HelloCMake
- This tells CMake you are defining a new project named
- line 4:
add_executable(hello main.cpp)
- This tells CMake to add a single executable named
hello
that is the result of compilingmain.cpp
- This tells CMake to add a single executable named
Easy-peasy. Now how is it used to build the software?
- Step 1: clone the gist
git clone https://gist.github.com/daniel-packard/4756acc129365f9d26d6ffbfe6738276 hello-cmake
- Step 2: open the CMake GUI
- Step 3: Locate the source code directory, using the
Browse Source
button- Note: you should select the directory containing your source code and CMakeLists.txt.
- Step 4: Locate the build directory, using the
Browse Build
button- By convention CMake encourages "out of tree" builds, meaning you select a different build directory. This helps with keeping your workspace tidy, and your build artifacts organized (i.e. easy to delete), and lets you do side-by-side builds for different platforms (e.g. by having two different build output directories: build-ios, build-x64-windows)
- in this case, I am creating a subdirectory inside my project called
build
- Step 5a: Press the
Configure
button- Follow the prompts to select your "generator" and compiler toolchain.
- In this case I'm building with Visual Studio 16 2019 and using the default native compiler toolchain
- Step 5b: Results of "Configure"
- Pressing
Finish
(if successful) will load the CMake build configuration and presents you with any configurable options/settings - In this case, there are only a couple built-in options from CMake. We'll come back to them later.
- Pressing
- Step 6: Press
Generate
to produce the build configuration- For me, this creates a visual studio solution
- Step 7: Build your project
- In my case, this involves: opening the solution, setting "hello" as the startup project, and pressing the "play" button
Success!
... or is it? Please send questions/problems to [email protected], and we'll develop a companion trouble-shooting guide.
Example 0 Recap
- Downloaded a project containing some source code and a CMakeLists.txt build configuration
- Configured the project using CMake for Visual Studio 2019, using my native compiler toolchain
- Generated a build configuration for my tools/platform of choice
- Built and ran the
hello
command line tool using Visual Studio