In the previous article, “Introduction to CMake Build Tool for ESP32,” we introduced the most basic usage of CMake with a “Hello World” program. Today, we will provide a detailed explanation of the CMakeLists.txt
file.
CMakeLists.txt
The CMakeLists.txt
file is the core configuration file for the CMake build tool. It contains a series of instructions and parameters necessary for building the project, and CMake will generate the corresponding build files based on this information. The CMakeLists.txt
file is usually located in the top-level directory of the project and can include other CMakeLists.txt
files in subdirectories to organize the build process of complex projects.
The CMakeLists.txt
file includes the following types of instructions:
-
Project settings: Define project name, version, target platform, and other information -
Specify source and header files: Specify the source and header files to be compiled in the project -
Add subdirectories: Include subdirectories in the build process, which may contain their own CMakeLists.txt
files -
Set compiler and linker options: For example, specify compilation flags, link libraries, etc. -
Add executable files and libraries: Specify the executable files, static libraries, or dynamic libraries to be generated -
Add dependencies and link libraries: Specify the external libraries and header file paths required by the project
Below is a simple example of a C language project’s CMakeLists.txt
file:
# Set the minimum required version of CMake
cmake_minimum_required(VERSION 3.10)
# Set project name and version
project(MyProject VERSION 1.0)
# Set C standard
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED True)
# Add subdirectory, which should contain its own CMakeLists.txt file
add_subdirectory(src)
# Specify source and header files
set(SOURCES main.c)
set(HEADERS include/myheader.h)
# Add executable file
add_executable(MyProject ${SOURCES} ${HEADERS})
# Add library
add_library(MyLibrary STATIC src/mylibrary.c)
# Add header file path for the library
target_include_directories(MyProject PUBLIC include)
# Add dependency library
target_link_libraries(MyProject PRIVATE MyLibrary)
In this example, we created a project named “MyProject” based on the C language, set the C11 standard, and added a static library named “MyLibrary.” We also specified the source files, header files, and library dependencies.
The CMakeLists.txt
file includes the following major syntax:
-
Comments: Lines starting with
#
indicate comments.Example:
# This is a comment
-
Variables: Use the
set()
function to set variable values and use variable values with${}
.Example:
set(SOURCE_FILES main.cpp) add_executable(my_app ${SOURCE_FILES})
-
Conditional control: Use
if()
,elseif()
,else()
, andendif()
for conditional control.Example:
if(WIN32) set(PLATFORM "Windows") elseif(APPLE) set(PLATFORM "macOS") elseif(UNIX) set(PLATFORM "Linux") else() message(FATAL_ERROR "Unsupported platform") endif()
-
Loops: Use
foreach()
related syntax for looping.Example:
set(SOURCE_FILES main.cpp file1.cpp file2.cpp) foreach(file ${SOURCE_FILES}) message("source file: ${file}") endforeach()
-
Functions and macros: Use
function()
andendfunction()
to define functions, and usemacro()
andendmacro()
to define macros.Example:
function(print_files files) foreach(file ${files}) message("file: ${file}") endforeach() endfunction() macro(my_macro arg1 arg2) message("arg1 is ${arg1}, arg2 is ${arg2}") endmacro() set(SOURCE_FILES main.cpp file1.cpp file2.cpp) print_files(${SOURCE_FILES}) my_macro("Hello" "World")
Example
Below is an example that integrates the above syntax:
# Set the minimum required version of CMake
cmake_minimum_required(VERSION 3.0)
# Create project hello_world
project(hello_world)
# Set C++11 standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Detect platform type
if(WIN32)
set(PLATFORM "Windows")
elseif(APPLE)
set(PLATFORM "macOS")
elseif(UNIX)
set(PLATFORM "Linux")
else()
# If the platform is not supported, give an error message
message(FATAL_ERROR "Unsupported platform")
endif()
# Define a function print_files to print file list
function(print_files)
foreach(file ${ARGN})
message("file: ${file}")
endforeach()
endfunction()
# Define a macro my_macro to print platform and processor information
macro(my_macro arg1 arg2)
message("PLATFORM is ${arg1}, CMAKE_HOST_SYSTEM_PROCESSOR is ${arg2}")
endmacro()
# Set file list
set(files main.cpp file1.cpp file2.cpp)
# Call print_files function to print file list
print_files(${files})
# Call my_macro macro to print platform and processor information
my_macro(${PLATFORM} ${CMAKE_HOST_SYSTEM_PROCESSOR})
# Add executable file hello_world
add_executable(hello_world main.cpp)
This is a basic CMakeLists.txt
file that mainly includes the following contents:
-
Set the minimum required version of CMake to 3.0. -
Create a project named hello_world. -
Set the C++11 standard. -
Detect the current platform type (Windows, macOS, or Linux) and store it in the PLATFORM variable. -
Define a function named print_files to print the file list. -
Define a macro named my_macro to print platform and processor information. -
Set a file list and print it using the print_files function. -
Call the my_macro macro to print platform and processor information. -
Add an executable file named hello_world with the source code from main.cpp.
Running result:
esp-test\hello\build via △ v3.24.3
❯ cmake ..
-- Selecting Windows SDK version 10.0.19041.0 to target Windows 10.0.19045.
file: main.cpp
file: file1.cpp
file: file2.cpp
PLATFORM is Windows, CMAKE_HOST_SYSTEM_PROCESSOR is AMD64
-- Configuring done
-- Generating done
-- Build files have been written to: C:/Users/yp.wang/Desktop/esp-test/hello/build
Although the basic syntax is not complicated, the combinations can vary widely, and with various built-in variables, the CMakeLists.txt
in actual large projects can be very complex, requiring continuous learning and accumulation. Fortunately, the CMake syntax is relatively simple and close to natural language, making it easy to understand when reading.