Introduction to CMake
Tags: cpp, tutorial, devops, beginners
Published: 2022-09-11 19:16:16

> For writing cross-platform applications

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 instruction 
	- `ctest`: for detecting and running tests 
	- `cpack`: 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](https://en.wikipedia.org/wiki/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 
1. Download CMake from: https://cmake.org/download/
	1. It is available as a pre-compiled binary or as a source code
2. Extract it into a folder and open the command line in that directory
3. Run the command `./configure make`
4. To install CMake, run the command `make install`
5. To check if the installation is successful, run `cmake --version`. It should print out the version of CMake, like this: 

```bash
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++. 

1. Execute `mkdir src` to create the following directory.
  ```
  └───src
  ```
2. Write the `main.cpp` inside the `src` directory: 
  ```Cpp
  #include <iostream>
  
  auto main() -> int {
  	std::cout << "hello, world! \n";	
  	return 0;
  }
  ```
3. Create `CMakeLists.txt` and add the following commands:
  ```cmake
  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
  )
  ```
4. Go to the project directory and execute `cmake -S . -B build` to make the build directory.
```bash
$ 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
```
6. Go to the `build` directory and run `make` to build the project.
```bash
$ cd build && make
Scanning dependencies of target HelloWorld
[ 50%] Building CXX object CMakeFiles/HelloWorld.dir/src/main.cpp.o
[100%] Linking CXX executable H
```
7. Execute the binary.


## The Build Process 
CMake build process is mainly broken down into two steps: configure and build. 
1. 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. 
2. 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


## References
1. D. Berner & M.K. Gilor (2022). CMake Best Practices. Packt Publishing. ISBN 9781803239729. 
2. CMake (2022). CMake Tutorial. https://cmake.org/cmake/help/latest/guide/tutorial/index.html
3. Wikipedia Contributors (2022). CMake. https://en.wikipedia.org/wiki/CMake
4. Cmake (2022). Why CMake? https://cmake.org/cmake/help/book/mastering-cmake/chapter/Why%20CMake.html