Learning CMakeLists.txt
Table of Contents
1. Brief Introduction to CMake
2. What is CMakeLists.txt?
3. Creating CMakeLists.txt
4. Other Notes
5. References
Brief Introduction to CMake
This article will help readers understand what CMakeLists.txt
is, why it is used, and provide instructions on how to create a CMakeLists.txt
. Before getting started, it is important to understand what CMake is. Note that the reader is presumed to have the very basic knowledge of C++, Make, and MakeFile.
Unlike Make, which is a build system that drives the compiler and other build tools to build your code, CMake (or Cross-platform Make) is a “generator” of build systems that can be used for general purpose builds. It is much more high-level such that it can generate a low-level build script in Ninja or Make or many other build systems that you can run with.
The key feature of CMake is that it supports the cross-platform discovery of system libraries, and automatic discovery and configuration of the toolchain, which is much easier to use than Make.
To install CMake, check their document on how to download and install on Unix/Linux or Windows.
What is CMakeLists.txt?
When CMake processes a project, the entry point is a source file called CMakeLists.txt
in the top level of the source directory.
CMakeLists.txt
is the CMake configuration file, which contains a set of directives and instructions describing the project’s source files and targets (executable, library, or both) that will be used to build the program. It determines everything for the building process, from which source files to compile, to which options to choose for the libraries and present to the users.
Here is a simple example of what it looks like:
# CMakeLists.txt
# The minimum version of CMake required
cmake_minimum_required(VERSION 3.10)
# Project name
project(MyProject)
# Add main.cpp file of the project root directory as a source file
set(SOURCE_FILES main.cpp)
# Add executable targets
add_executable(MyExecutable ${SOURCE_FILES})
Creating CMakeLists.txt
CMake Language
CMakeLists.txt
is written in CMake Language, which consists of comments, commands, and variables.
- Comments start with
#
# This is a comment
- Commands start with command names and a list of whitespace-separated arguments (case-sensitive).
find_package(LIBIGL REQUIRED QUIET)
-
Variables are case-sensitive with only alphanumeric characters and underscores.
A number of useful variables are automatically defined by CMake (e.g
CMAKE_CURRENT_SOURCE_DIR
,PROJECT_NAME
).Use the set command to set variable names, and ${variable_name} to reference a varible in command arguments.
set(Foo a b c) # Value of Foo is "a;b;c" command(${Foo}) # Foo is replaced by a;b;c # and expands to 3 arguments
CMake also provides basic control flow statements - conditional statements, looping constructs, and procedure definitions. Here are the examples:
- Conditional statements (e.g if)
if(<condition>) <commands> elseif(<condition>) # optional block, can be repeated <commands> else() # optional block <commands> endif()
- Looping constructs (e.g foreach, while)
foreach(<variable> # similar to `for <variable> in <items>` in python. <items>) # list of items that are separated by semicolon or whitespace command(${variable} <arguments>) # ${variable} - current value from the list endforeach() while(<condition>) <commands> endwhile()
- Procedure definitions (e.g function, macro)
function(<function_name> <parameters>) <commands> endfunction() macro(<macro_name> <parameters>) <commands> endmacro()
For more detailed information on CMake Language, check the highlighted links above.
Key Components and Concepts
A CMakeLists.txt
typically consists of the following elements:
-
cmake_minimum_required
CMake version check: the minimum version of CMake that should be used to process the project.
cmake_minimum_required(VERSION 3.10)
You can specify a range of versions (as a general rule, set the highest version you’ve tested with):
cmake_minimum_required(VERSION 3.15...3.25)
-
project
Create project with the name of the project that is given to the cmake command.
project(MyProject)
Projects can have versions, descriptions and languages specified.
project(MyProject VERSION 1.0 DESCRIPTION "A project" LANGUAGES CXX )
-
Set a source file
# Add main.cpp file of the project root directory as a source file set(SOURCE_FILES main.cpp)
-
add_executable
add_executable(MyExecutable ${SOURCE_FILES})
Add executable target named
MyExecutable
with source files listed in theSOURCE_FILES
variable
Other components
- Variables and Options can be set in
CMakeLists.txt
to control various aspects of the building process.set(CMAKE_CXX_STANDARD 14) # enables the c++14 standards option(BUILD_TESTS "Build tests" ON) # build options - whether to build tests
- Include your directories and headerfiles
# Adds directories to the compiler's include path. include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include/")
- Include your source files
Suppose this is your project structure:
project_root/ |-- CMakeLists.txt |-- src/ | |-- file1.cpp | |-- file2.cpp | |-- ... |-- other_files/ | |-- ... |-- main.cpp
You can add the source files in the
src
directory by:file(GLOB SRC_FILES "*.cpp") # Create a library or executable target using the source files add_library(my_library ${SRC_FILES}) target_link_libraries(MyExecutable my_library)
- External Libraries can be located using
find_package
# Appends the "cmake" directory to the module path # CMake modules are used to find and configure external libraries. set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake) find_package(PACKAGE_NAME) # Locate the package with PACKAGE_NAME if(PACKAGE_NAME_FOUND) # PACKAGE_NAME_FOUND is automatically generated by find_package() target_link_libraries ( MyExecutable <libaries> # Links against the libraries within the package. ) endif()
The if-condition can be omitted if you specify the “REQUIRED”:
find_package(PACKAGE_NAME REQUIRED)
Other Notes
-
Within any of the supported generators (Visual Studio, etc.), there are rules that will automatically invoke CMake to update the generated files, including MakeFiles or project files, whenever you edit a
CMakeLists.txt
file and rebuild. -
There are many more CMake variables and commands that are useful in building a
CMakelists.txt
. Here is a cheatsheet that consists of most of the popular variables/commands.