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.txt
to 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.