CMake is a cross-platform build system generator that is widely used in C++ projects to manage the build process. It generates native makefiles or project files for IDEs (like Visual Studio, Xcode, etc.), allowing you to build your project on different platforms in a standardized way.
Table of Contents
🔹 1. CMake Basics: What is CMake?
CMake is a tool that helps manage the build process of a project in a platform-independent manner. It doesn’t directly compile the code but generates the necessary build scripts (e.g., Makefile, Visual Studio project files, etc.) based on CMakeLists.txt files, which describe the project structure and build instructions.
🔹 2. Basic Structure of a CMake Project
A simple CMake project typically consists of:
- CMakeLists.txt: The main configuration file that specifies the project’s build instructions.
- Source files: The actual code files that need to be compiled.
- Build directory: Where CMake generates the necessary build files.
Example Directory Structure:
/your_project
├── CMakeLists.txt
├── src/
├── main.cpp
├── my_class.cpp
└── my_class.h
🔹 3. A Simple CMakeLists.txt File
Here’s a basic CMakeLists.txt file for a simple C++ project:
CMakeLists.txt (Simple Project)
# Set the minimum required version of CMake
cmake_minimum_required(VERSION 3.10)
# Define the project name and version
project(MyProject VERSION 1.0)
# Add the executable to be built (specify source files)
add_executable(MyProject src/main.cpp src/my_class.cpp)
# Optionally link libraries (e.g., Boost, pthread, etc.)
# target_link_libraries(MyProject Boost::Boost pthread)
Explanation:
cmake_minimum_required(VERSION 3.10): Ensures that CMake version 3.10 or higher is used.project(MyProject VERSION 1.0): Defines the project name and version.add_executable(MyProject src/main.cpp src/my_class.cpp): Specifies the source files for the executable.
🔹 4. Running CMake
Step 1: Create a Build Directory
It’s recommended to create a separate directory to store the build files.
mkdir build
cd build
Step 2: Run CMake
To configure the project and generate the build files:
cmake ..
This command tells CMake to look for the CMakeLists.txt in the parent directory (..) and generate the necessary build system files (e.g., Makefile, Visual Studio project).
Step 3: Build the Project
Once the build system files are generated, you can use make (on Unix-like systems) or other tools (e.g., Visual Studio, Xcode) to build the project:
make
🔹 5. Advanced CMake Features
1. Adding Libraries
You can add libraries (both static and dynamic) using add_library() and link them with your target using target_link_libraries().
Example: Adding Static Library
# Create a static library
add_library(MyLibrary STATIC src/my_class.cpp)
# Link the library to the executable
add_executable(MyProject src/main.cpp)
target_link_libraries(MyProject MyLibrary)
2. Defining Compiler Options
You can specify compiler flags or options to control how your code is compiled:
# Set the C++ standard
set(CMAKE_CXX_STANDARD 17)
# Add compiler flags (e.g., optimization level)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
3. Find and Link External Libraries
For libraries like Boost, CMake can find and link them automatically using find_package().
find_package(Boost 1.70 REQUIRED)
# Link Boost libraries
target_link_libraries(MyProject Boost::Boost)
4. Conditional Compilation
You can use if() statements to compile parts of the code conditionally based on platform, architecture, or other conditions.
if(WIN32)
# Code for Windows platform
elseif(APPLE)
# Code for macOS platform
else()
# Code for Linux or other platforms
endif()
5. Adding Custom Commands
You can specify custom build commands using add_custom_command().
add_custom_command(TARGET MyProject POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_SOURCE_DIR}/data/some_file.txt
${CMAKE_BINARY_DIR}/some_file.txt)
🔹 6. CMake for Multiple Directories (Subdirectories)
For larger projects, you may want to organize the project into multiple directories (e.g., separate folders for src, include, etc.). You can use add_subdirectory() to include subdirectories.
Example project structure:
/your_project
├── CMakeLists.txt
├── src/
├── include/
├── lib/
Root CMakeLists.txt:
cmake_minimum_required(VERSION 3.10)
project(MyProject)
# Add subdirectories
add_subdirectory(src)
add_subdirectory(lib)
Subdirectory CMakeLists.txt (src/):
add_executable(MyProject src/main.cpp)
🔹 7. Building and Testing with CMake
Unit Testing with CMake
CMake has built-in support for unit testing using CTest. Here’s how you can add Google Test to your project for testing.
Add Google Test:
git clone https://github.com/google/googletest.git
Modify CMakeLists.txt to include tests:
# Add Google Test
add_subdirectory(googletest)
# Create a test executable
add_executable(MyTests test/main_test.cpp)
# Link Google Test libraries
target_link_libraries(MyTests gtest gtest_main)
# Add CTest for testing
enable_testing()
add_test(NAME MyTests COMMAND MyTests)
Now you can run tests with:
ctest
🔹 8. Common CMake Commands
- cmake –version: Check the installed CMake version.
- cmake –build .: Build the project (equivalent to
make). - cmake –install .: Install the built project.
- cmake –help: Show CMake help documentation.
🔹 9. Conclusion
CMake is a powerful and flexible build system generator that helps simplify the process of building C++ projects across different platforms. It abstracts away platform-specific details and helps in managing complex projects with dependencies, libraries, and multiple configurations.
Key Points to Remember:
- Use
CMakeLists.txtto define your project. - Keep your source files in separate directories for better organization.
- Use
find_package()to link external libraries like Boost or Google Test. - For large projects, split them into multiple directories and manage them using
add_subdirectory(). - Use CTest for integrating unit tests in your build system.