目錄
1.CMakeLists.txt基本結構
2.核心語法規則
3.關鍵命令詳解
4.常用預定義變量
5.變量和緩存
6.變量作用域與傳遞
7.注意事項
1.CMakeLists.txt基本結構
????????CMakeLists.txt 是 CMake 構建系統的核心配置文件,采用命令式語法組織項目結構和編譯流程。主要用于定義項目的構建規則、依賴關系、編譯選項等。每個 CMake 項目通常都有一個或多個 CMakeLists.txt 文件。
????????一個完整的 CMakeLists.txt 通常包含以下部分:
# 1. CMake 最低版本要求
cmake_minimum_required(VERSION 3.10)# 2. 項目信息
project(MyProject VERSION 1.0.0 LANGUAGES CXX)# 3. 全局配置(可選)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # 生成 compile_commands.json# 4. 查找依賴(可選)
find_package(Threads REQUIRED)
find_package(Boost 1.70 COMPONENTS system REQUIRED)# 5. 添加子目錄(可選)
add_subdirectory(src)
add_subdirectory(tests)# 6. 定義目標(可執行文件或庫)
add_executable(myapp main.cpp)
add_library(mylib STATIC src/lib.cpp src/utils.cpp)# 7. 配置目標屬性
target_include_directories(mylib PUBLIC include)
target_link_libraries(myapp PRIVATE mylib Threads::Threads)
target_compile_definitions(myapp PRIVATE DEBUG_MODE=1)# 8. 安裝規則(可選)
install(TARGETS myapp DESTINATION bin)
install(FILES include/mylib.h DESTINATION include)# 9. 測試配置(可選)
enable_testing()
add_test(NAME MyTest COMMAND myapp_test)
2.核心語法規則
1.命令格式
command(arg1 arg2 ...) # 命令名不區分大小寫,但參數區分
- 命令和參數用空格或括號分隔。
- 參數可用雙引號括起(如包含空格時):
set(NAME "My Project")
。
2.變量引用
set(SOURCE_FILES main.cpp src/foo.cpp)
add_executable(myapp ${SOURCE_FILES}) # 使用 ${} 引用變量
- 變量作用域:當前目錄及子目錄,可用?
PARENT_SCOPE
?提升作用域。
3.注釋
# 單行注釋
4.條件語句
if(WIN32)set(PLATFORM_LIBS ws2_32)
else()set(PLATFORM_LIBS pthread)
endif()target_link_libraries(myapp PRIVATE ${PLATFORM_LIBS})
- 條件表達式:
WIN32
、APPLE
、UNIX
、DEFINED var
、NOT
、AND
、OR
?等。
5.循環
foreach(file IN LISTS source_files)message("Processing file: ${file}")
endforeach()
6.函數和宏
# 函數(有獨立作用域)
function(print_info name)message("Project name: ${name}")
endfunction()# 宏(直接替換)
macro(add_example name)add_executable(${name} examples/${name}.cpp)
endmacro()print_info(${PROJECT_NAME})
add_example(example1)
3.關鍵命令詳解
1.項目設置
cmake_minimum_required(VERSION <version>)
:指定所需的最低 CMake 版本。project(<name> [VERSION <ver>] [LANGUAGES <langs>])
:定義項目名稱、版本和支持的語言。
示例如下:
#1
cmake_minimum_required(VERSION 3.10)
#2
project(MyProject CXX)
2.目標定義
add_executable(<name> <sources>)
:創建可執行文件。add_library(<name> [STATIC|SHARED|MODULE] <sources>)
:創建庫(靜態 / 共享 / 模塊)。add_custom_target(<name> [COMMAND <cmd>] [DEPENDS <deps>])
:創建自定義目標(如構建腳本)。
示例代碼:
#1
add_executable(MyExecutable main.cpp other_file.cpp)
#2
add_library(MyLibrary STATIC library.cpp)
#3
add_library(MyLibrary SHARED library.cpp)
3.依賴管理
find_package(<package> [REQUIRED] [VERSION <ver>])
:查找并導入外部包。add_subdirectory(<dir>)
:添加子目錄中的 CMakeLists.txt。target_link_libraries(<target> <PRIVATE|PUBLIC|INTERFACE> <libs>)
:鏈接庫到目標。-
include_directories(<dirs>...)
示例代碼:
#1
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets Network)
find_package(Qt${QT_VERSION_MAJOR} CONFIG REQUIRED COMPONENTS Widgets Network)#2
add_subdirectory(tutorial)#3
target_link_libraries(QSimpleUpdater PUBLIC Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Widgets PRIVATE Qt${QT_VERSION_MAJOR}::Network)#4
include_directories(${PROJECT_SOURCE_DIR}/include)
4.編譯選項
target_include_directories(<target> <PRIVATE|PUBLIC|INTERFACE> <dirs>)
:添加頭文件搜索路徑。target_compile_definitions(<target> <PRIVATE|PUBLIC|INTERFACE> <defs>)
:添加編譯定義(如?-DDEBUG
)。target_compile_options(<target> <PRIVATE|PUBLIC|INTERFACE> <options>)
:添加編譯選項(如?-Wall
)。
示例代碼:
#1
target_include_directories(QSimpleUpdater PUBLIC include)
5.安裝規則
install(TARGETS target1 [target2 ...][RUNTIME DESTINATION dir][LIBRARY DESTINATION dir][ARCHIVE DESTINATION dir][INCLUDES DESTINATION [dir ...]][PRIVATE_HEADER DESTINATION dir][PUBLIC_HEADER DESTINATION dir])
示例代碼:
#1
install(TARGETS <targets>RUNTIME DESTINATION binLIBRARY DESTINATION libARCHIVE DESTINATION lib/static)install(FILES <files> DESTINATION include)
install(DIRECTORY <dir> DESTINATION share)#2
install(TARGETS MyExecutable RUNTIME DESTINATION bin)
6.自定義命令 (add_custom_command 命令)
add_custom_command(TARGET targetPRE_BUILD | PRE_LINK | POST_BUILDCOMMAND command1 [ARGS] [WORKING_DIRECTORY dir][COMMAND command2 [ARGS]][DEPENDS [depend1 [depend2 ...]]][COMMENT comment][VERBATIM]
)
示例代碼:
add_custom_command(TARGET MyExecutable POST_BUILDCOMMAND ${CMAKE_COMMAND} -E echo "Build completed."
)
7.測試配置
enable_testing()
add_test(NAME <test_name> COMMAND <executable> <args>)
add_test(NAME <test_name> WORKING_DIRECTORY <dir> COMMAND <cmd>)
4.常用預定義變量
1. 項目信息
變量名 | 描述 | 示例值 |
---|---|---|
PROJECT_NAME | 當前項目名稱 | MyProject |
PROJECT_VERSION | 項目版本(通過?project() ?設置) | 1.2.3 |
PROJECT_SOURCE_DIR | 當前項目的源目錄 | /path/to/myproject |
PROJECT_BINARY_DIR | 當前項目的構建目錄 | /path/to/myproject/build |
2.路徑相關
變量名 | 描述 | 示例值 |
---|---|---|
CMAKE_SOURCE_DIR | 頂級 CMakeLists.txt 所在目錄 | /path/to/myproject |
CMAKE_BINARY_DIR | 頂級構建目錄 | /path/to/myproject/build |
CMAKE_CURRENT_SOURCE_DIR | 當前 CMakeLists.txt 所在目錄 | /path/to/myproject/src |
CMAKE_CURRENT_BINARY_DIR | 當前構建目錄 | /path/to/myproject/build/src |
CMAKE_INSTALL_PREFIX | 安裝路徑前綴 | /usr/local (默認) |
LIBRARY_OUTPUT_PATH | 庫文件輸出的默認路徑 | 庫路徑不設置的話,默認放在BINARY_DIR下,即構建時執行cmake命令的目錄下 |
3.構建配置
變量名 | 描述 | 示例值 |
---|---|---|
CMAKE_BUILD_TYPE | 構建類型 | Debug ,?Release ,?RelWithDebInfo |
CMAKE_C_COMPILER | C 編譯器路徑 | /usr/bin/gcc |
CMAKE_CXX_COMPILER | C++ 編譯器路徑 | /usr/bin/g++ |
CMAKE_CXX_STANDARD | C++ 標準版本 | 11 ,?14 ,?17 ,?20 |
CMAKE_GENERATOR | 當前使用的生成器 | Unix Makefiles ,?Ninja |
CMAKE_C_STANDARD_REQUIRED |
| |
CMAKE_CXX_STANDARD_REQUIRED |
| set(CMAKE_CXX_STANDARD 20) # 指定 C++ 標準為 C++20 set(CMAKE_CXX_STANDARD_REQUIRED ON) # 強制要求此標準 |
| | |
4.系統信息
變量名 | 描述 | 示例值 |
---|---|---|
CMAKE_SYSTEM_NAME | 操作系統名稱 | Linux ,?Windows ,?Darwin |
CMAKE_SYSTEM_VERSION | 系統版本 | 10.0 (Windows) |
CMAKE_HOST_SYSTEM_PROCESSOR | 處理器架構 | x86_64 ,?arm64 |
5.目標屬性(Target Properties)
通過?set_target_properties
?或?get_target_property
?操作,影響特定目標的行為。
常用屬性
屬性名 | 描述 | 設置命令 |
---|---|---|
OUTPUT_NAME | 輸出文件名 | set_target_properties(myapp PROPERTIES OUTPUT_NAME "custom_name") |
VERSION | 庫版本號 | set_target_properties(mylib PROPERTIES VERSION "1.2.3") |
SOVERSION | 共享庫 API 版本 | set_target_properties(mylib PROPERTIES SOVERSION "1") |
COMPILE_DEFINITIONS | 編譯定義(如?-DDEBUG ) | target_compile_definitions(myapp PRIVATE DEBUG) |
INCLUDE_DIRECTORIES | 頭文件搜索路徑 | target_include_directories(myapp PUBLIC include) |
LINK_LIBRARIES | 鏈接庫 | target_link_libraries(myapp PRIVATE pthread) |
POSITION_INDEPENDENT_CODE | 是否生成位置無關代碼(共享庫必需) | set_target_properties(mylib PROPERTIES POSITION_INDEPENDENT_CODE ON) |
5.變量和緩存
CMake 使用變量來存儲和傳遞信息,這些變量可以在 CMakeLists.txt 文件中定義和使用。
變量可以分為普通變量和緩存變量。
1.變量定義與使用
定義變量:
set(MY_VAR "Hello World")
使用變量:
message(STATUS "Variable MY_VAR is ${MY_VAR}")
2.緩存變量
緩存變量存儲在 CMake 的緩存文件中,用戶可以在 CMake 配置時修改這些值。緩存變量通常用于用戶輸入的設置,用戶可通過命令行(-D
)或 CMake GUI 修改,例如編譯選項和路徑。
定義緩存變量:
set(MY_CACHE_VAR "DefaultValue" CACHE STRING "A cache variable")set(BUILD_SHARED_LIBS ON CACHE BOOL "Build shared libraries")
set(CMAKE_INSTALL_PREFIX "/usr/local" CACHE PATH "Installation directory")
使用緩存變量:
message(STATUS "Cache variable MY_CACHE_VAR is ${MY_CACHE_VAR}")
3.環境變量
- 訪問方式:
$ENV{VARIABLE_NAME}
- 修改方式:
set(ENV{VARIABLE_NAME} value)
message("PATH: $ENV{PATH}") # 讀取環境變量
set(ENV{MY_LIB_PATH} "${CMAKE_SOURCE_DIR}/libs") # 設置環境變量
6.變量作用域與傳遞
- 默認作用域:當前目錄及子目錄。
- 提升作用域:
PARENT_SCOPE
?參數。
# 在子目錄 CMakeLists.txt 中
set(CHILD_VAR "value" PARENT_SCOPE) # 將變量傳遞到父目錄
7.注意事項
1.模塊化結構
project/
├── CMakeLists.txt # 頂級配置
├── src/ # 源代碼
│ └── CMakeLists.txt
├── include/ # 公共頭文件
├── tests/ # 測試代碼
│ └── CMakeLists.txt
├── examples/ # 示例
└── CMakeModules/ # 自定義 CMake 模塊
2.使用現代 CMake 模式
- 優先使用?
target_*
?命令(如?target_include_directories
)而非全局設置。 - 通過?
PUBLIC/PRIVATE/INTERFACE
?明確依賴范圍。
3.避免硬編碼路徑
# 不好的做法
include_directories("/usr/local/include/mylib")# 好的做法
find_package(MyLib REQUIRED)
target_link_libraries(myapp PRIVATE MyLib::MyLib)
4.添加版本控制
project(MyProject VERSION 1.2.3)
configure_file(version.h.in version.h)
target_include_directories(myapp PRIVATE ${CMAKE_BINARY_DIR})
掌握 CMakeLists.txt 的結構和語法是高效管理 C/C++ 項目的關鍵,合理組織文件可大幅提升項目的可維護性和跨平臺兼容性。
相關鏈接
- CMake 官網?CMake - Upgrade Your Software Build System
- CMake 官方文檔:CMake Tutorial — CMake 4.0.2 Documentation
- CMake 源碼:https://github.com/Kitware/CMake
- CMake 源碼:Sign in · GitLab