At some point in our C++ journey, we meet tools that improve our project's maintainability. Configuring build systems help us relieve the overhead of writing multiple makefiles for different platforms. This ensures that we can be able to build and deploy software across multiple platforms.
It's been only 3 months since I first integrated CMake into my C++ projects. And since then, I'm able to write my program without worrying about different compilers, and Operating Systems it will run on. It allowed me to focus more on the work. Indeed, it has added value both to my development experience and my projects. So I'm starting this series to document the things I learned from Dominik Berner, and Mustafa Kemal Gilor's (2022) book: CMake Best Practices.
In this article, I will briefly cover CMake and take you through an overview of its build process. And on the next part, we will look at CMake as a scripting language.
What is CMake?
- CMake is an open-source project that serves as a tool for building, testing, packaging, and distributing cross-platform software
- CMake is a scripting language written in C++
- CMake is a de facto industry standard for building C++ projects
- CMake is divided into 3 command-line tools:
cmake
: for generating compiler-independent build instructionctest
: for detecting and running testscpack
: for packing the software project into convenient installers
Benefits of using CMake
- Provides an interface to configure a compiler-independent build
- Separate the source code directory and the compiler outputs: enable building multiple builds from the same source tree
- Supports cross-compilation
- Enables CI/CD automation for testing and building the project*
- Integrates well with package managers such as Conan
- Improves the project's maintainability by providing a single point of definitions from build configuration, testing, and packaging specifications
Installing CMake
- Download CMake from: cmake.org/download
- It is available as a pre-compiled binary or as a source code
- Extract it into a folder and open the command line in that directory
- Run the command
./configure make
- To install CMake, run the command
make install
- To check if the installation is successful, run
cmake --version
. It should print out the version of CMake, like this:
C:\Users\[username]\[path]>cmake --version
cmake version 3.22.1
CMake suite is maintained and supported by Kitware (kitware.com/cmake).
Hello, World!
in CMake
Before writing your C++ project, it is good practice to test out the build configuration first. This section briefly walks you through the minimal CMake configuration for hello, world!
in C++.
- Execute
mkdir src
to create the following directory.└───src
Write the
main.cpp
inside thesrc
directory:#include <iostream> auto main() -> int { std::cout << "hello, world! \n"; return 0; }
- Create
CMakeLists.txt
and add the following commands:cmake_minimum_required(VERSION 3.10) # set project name, version, description, and language specification project( "HelloWorld" VERSION 1.0 DESCRIPTION "Hello World in CMake" LANGUAGES CXX ) # tells CMake to build an executable add_executable(${PROJECT_NAME}) # tells CMake which location to look for the sources of the executable target_sources(${PROJECT_NAME} PRIVATE src/main.cpp )
- Go to the project directory and execute
cmake -S . -B build
to make the build directory.$ cmake -S . -B build -- The CXX compiler identification is GNU 10.3.0 -- Check for working CXX compiler: /usr/bin/c++ -- Check for working CXX compiler: /usr/bin/c++ -- works -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Detecting CXX compile features -- Detecting CXX compile features - done -- Configuring done -- Generating done -- Build files have been written to: [ProjectFolder]/build
- Go to the
build
directory and runmake
to build the project.$ cd build && make Scanning dependencies of target HelloWorld [ 50%] Building CXX object CMakeFiles/HelloWorld.dir/src/main.cpp.o [100%] Linking CXX executable H
- Execute the binary.
The Build Process
CMake build process is mainly broken down into two steps: configure and build.
- Configure (triggered by the command
cmake -S . -B build
): CMake searches for any usable toolchain available and decides which configuration it outputs; The standard output is Unix Makefiles but in the event where Microsoft Visual Studio Compiler (MSVC) is detected*.sln
file will be created instead.- During this process,
CMakeLists.txt
is parsed and executed to configure the build files relative to the toolchains, architecture, and dependencies. - CMake writes build files based on the generators; it can be changed using
cmake . -G [generator]
command.
- During this process,
- Build (triggered by the command
make
): CMake will execute the build files to compile and link binaries, run tests, and pack artifacts.- The
build
directory will contain the generated binaries, artifacts, build instructions, and cache - Inside the
build
directory,CMakeCache.txt
file will contain all the detected configurations
- The
References
- D. Berner & M.K. Gilor (2022). CMake Best Practices. Packt Publishing. ISBN 9781803239729.
- CMake (2022). CMake Tutorial. cmake.org/cmake/help/latest/guide/tutorial/..
- Wikipedia Contributors (2022). CMake. en.wikipedia.org/wiki/CMake
- Cmake (2022). Why CMake? cmake.org/cmake/help/book/mastering-cmake/c..