详解CMake命令与操作
本文最后更新于 31 天前,其中的信息可能已经有所发展或是发生改变。

平时在项目中使用,用的时候现搜,正好这次整理一下。

1. CMake基本概念与用法

1.1 基本概念

CMake是一个开源的跨平台构建系统,用于自动化生成平台特定的构建文件(如Makefile或Visual Studio项目)。其核心组件包括:

  • CMakeLists.txt:配置文件,定义项目结构、依赖关系和编译规则。
  • 构建目录(Build Directory):用于存放生成的构建文件,与源代码分离,保持整洁。
  • 生成器(Generator):工具链(如Unix Makefiles、Ninja或Visual Studio),将CMakeLists.txt转换为本地构建系统文件。
    CMake不直接编译代码,而是生成中间文件,由本地工具(如make或MSBuild)执行构建,简化跨平台开发流程。

1.2 核心特性

  • 跨平台性:支持Linux、Windows、macOS等系统,生成适配不同编译器的构建文件(如Xcode或MSVC项目)。
  • 高效性与可扩展性:优化大型项目管理(如KDE项目),构建速度比传统工具(如Autotools)快40%。
  • 模块化设计:通过find_package等命令自动检测系统库,简化依赖管理。
  • 声明式语法:CMakeLists.txt使用简洁的脚本语言,降低构建配置复杂度。

1.3 基本用法

CMake工作流程分为三步:

  1. 创建CMakeLists.txt:在项目根目录定义最小配置。

    cmake_minimum_required(VERSION 3.10)  # 指定最低CMake版本
    project(MyProject LANGUAGES CXX)      # 定义项目名称及语言(C++)
    add_executable(app main.cpp)          # 添加可执行文件目标
  2. 生成构建系统:在构建目录运行cmake命令。

    mkdir build && cd build
    cmake ..  # 生成Makefile或等效文件
  3. 构建项目:使用本地工具编译。

    make  # 或ninja、msbuild等

    此流程确保源码与构建分离,提升可维护性。


2. CMake详细命令

以下命令分类整理自CMake官方文档(v3.28)及实践案例,覆盖常用场景。命令按功能分组,并标注关键参数。

2.1 必备命令

命令 描述
cmake_minimum_required(VERSION x.x.x) 设置项目所需的最低 CMake 版本
project(<name> [LANGUAGES] [<language>...]) 定义项目名称及使用的语言(如 CXX、C)

2.2 子项目管理

命令 描述
add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL]) 添加一个子目录作为子项目
subdirs([dir1 dir2 ...]) 已弃用,旧版用于添加多个子目录
aux_source_directory(<dir> <variable>) 收集指定目录下的所有源文件到变量中
file(GLOB ...) 使用通配符匹配文件(如 *.cpp)并存入变量

2.3 目标管理

命令 描述
add_executable(<name> [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL] source1 ...) 创建可执行文件目标
add_library(<name> [STATIC | SHARED | MODULE] source1 ...) 创建库目标(静态/共享/模块)
target_sources(<target> [PRIVATE|PUBLIC|INTERFACE] source1 ...) 向目标添加源文件
target_include_directories(<target> [SYSTEM] [BEFORE] INTERFACE|PUBLIC|PRIVATE [items...] 设置目标的头文件包含路径
target_compile_definitions(<target> [PRIVATE|PUBLIC|INTERFACE] [items...] 设置编译宏定义
target_link_libraries(<target> [PRIVATE|PUBLIC|INTERFACE] lib1 ...) 链接库到目标
target_compile_options(<target> [PRIVATE|PUBLIC|INTERFACE] [items...] 设置编译器选项
target_link_options(<target> ...) 设置链接器选项

2.4 包管理

命令 描述
find_package(<PackageName> [version] [EXACT] [QUIET] [MODULE] [REQUIRED] [COMPONENTS ...]) 查找系统中的第三方库或工具
find_path(<VAR> name path1 path2 ...) 查找头文件路径
find_library(<VAR> name path1 path2 ...) 查找库文件路径
find_file(...) 查找普通文件
find_program(...) 查找可执行程序

2.5 变量与控制流

命令 描述
set(<var> [value] [CACHE TYPE DOCSTRING [FORCE]]) 设置变量值
unset(<var> [CACHE]) 删除变量
if(expression) / elseif() / else() / endif() 条件判断语句块
while(condition) / endwhile() 循环语句块
foreach(loop_var arg1 arg2 ...) ... endforeach() 遍历循环
message([STATUS|WARNING|SEND_ERROR|FATAL_ERROR] "message") 输出信息到控制台
option(<option_var> "description" [ON|OFF]) 定义用户可配置的布尔选项

2.6 文件及路径操作

命令 描述
file(WRITE filename "content") 写入内容到文件
file(APPEND filename "content") 追加内容到文件
file(READ filename variable) 读取文件内容到变量
file(MAKE_DIRECTORY dir1 dir2 ...) 创建目录
file(REMOVE file1 file2 ...) 删除文件
file(COPY src DESTINATION dest) 复制文件或目录
file(TO_CMAKE_PATH path result) 转换路径格式为 CMake 格式
file(TO_NATIVE_PATH path result) 转换路径为本地系统格式

2.7 宏与函数

命令 描述
macro(<name> [arg1 [arg2 [...]]]) ... endmacro() 定义宏
function(<name> [arg1 [arg2 [...]]]) ... endfunction() 定义函数

2.8 安装与打包

命令 描述
install(TARGETS targets... DESTINATION dir) 安装目标(如可执行文件、库)
install(FILES files... DESTINATION dir) 安装普通文件
install(DIRECTORY dir... DESTINATION dir) 安装整个目录
include(CPack) 启用 CPack 打包功能
cpack_add_install(CPACK_<OPTION>) 配置 CPack 打包参数

2.9 测试支持

命令 描述
enable_testing() 启用测试支持
add_test(NAME name COMMAND cmd [args...] [WORKING_DIRECTORY dir] [COMMENT comment] [DEPENDS dep1 dep2 ...]) 添加测试用例
set_tests_properties(test1 test2 ... PROPERTIES prop1 value1 ...) 设置测试属性

2.10 其他命令

命令 描述
add_custom_target(name [ALL] [command1 [args...]] [DEPENDS depend1 ...] [WORKING_DIRECTORY dir]) 添加自定义目标(如生成资源)
add_custom_command(...) 添加自定义构建命令
execute_process(COMMAND cmd [args...] [WORKING_DIRECTORY dir] [RESULT_VARIABLE var] [OUTPUT_VARIABLE out] [ERROR_VARIABLE err]) 执行外部进程
list(APPEND|INSERT|REMOVE_AT|REMOVE_ITEM|SORT list_var ...) 列表操作
string(FIND|REPLACE|TOLOWER|TOUPPER|SUBSTRING ...) 字符串操作
configure_file(input output) 替换模板文件中的变量并生成新文件


3. 使用示例

3.1 一般项目管理

以下是一个简单的Hello World项目示例,展示CMakeLists.txt的基本结构:

cmake_minimum_required(VERSION 3.10)  # 最低CMake版本
project(HelloWorld LANGUAGES CXX)     # 项目名及语言

# 添加可执行目标
add_executable(hello main.cpp)

# 设置C++标准
set(CMAKE_CXX_STANDARD 11)

# 可选:添加头文件目录
target_include_directories(hello PUBLIC include)

# 可选:链接库
# target_link_libraries(hello PRIVATE mylib)

构建步骤

  1. 创建build目录:mkdir build && cd build
  2. 生成构建文件:cmake ..
  3. 编译:make(或等效命令)

3.2 Qt项目CMake完整示例

3.2.1 CMakeLists.txt文件示例

# 基础配置段
cmake_minimum_required(VERSION 3.14)

# 项目级变量预设
set(LIB_NAME "qtadvanced")
set(PROJECT_VERSION 1.2.0)
set(VCPKG_TARGET_TRIPLET "x64-windows" CACHE STRING "VCPKG目标平台三元组")

# 工具链配置
if(DEFINED ENV{VCPKG_ROOT})
    set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
        CACHE STRING "VCPKG工具链文件路径")
endif()

# 自定义Qt路径支持
if(QT_CUSTOM_PATH)
    set(Qt5_DIR "${QT_CUSTOM_PATH}/lib/cmake/Qt5")
    set(QT_QMAKE_EXECUTABLE "${QT_CUSTOM_PATH}/bin/qmake")
endif()

# 项目定义
project(${LIB_NAME}
    VERSION ${PROJECT_VERSION}
    LANGUAGES CXX
    DESCRIPTION "Advanced Qt Component Library"
)

## Qt模块配置段
# 自动处理Qt元对象系统
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)

# 查找Qt组件
find_package(Qt5 COMPONENTS
    Core
    Widgets
    Qml
    Quick
    Gui
    REQUIRED
)

# 编译器配置
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

if(MSVC)
    add_compile_definitions(
        WIN32_LEAN_AND_MEAN
        NOMINMAX
        _CRT_SECURE_NO_WARNINGS
    )
    add_compile_options(/MP)  # 启用多核编译
endif()

## 源文件收集段
file(GLOB_RECURSE LIB_SOURCES 
    "src/*.cpp"
    "src/*.h"
)
file(GLOB_RECURSE UI_FILES
    "ui/*.ui"
)
file(GLOB_RECURSE QML_FILES
    "qml/*.qml"
)
file(GLOB_RECURSE RESOURCE_FILES
    "resources/*.qrc"
)

# 翻译支持
set(TS_FILES
    translations/${LIB_NAME}_en_US.ts
    translations/${LIB_NAME}_zh_CN.ts
)

## 目标构建段
add_library(${LIB_NAME} SHARED
    ${LIB_SOURCES}
    ${UI_FILES}
    ${RESOURCE_FILES}
    ${TS_FILES}
)

# 目标属性配置
set_target_properties(${LIB_NAME} PROPERTIES
    VERSION ${PROJECT_VERSION}
    SOVERSION 1
    OUTPUT_NAME "${LIB_NAME}$<$<CONFIG:Debug>:d>"
    WINDOWS_EXPORT_ALL_SYMBOLS ON  # Windows下自动导出符号
)

# 包含目录配置
target_include_directories(${LIB_NAME} PUBLIC
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
    $<INSTALL_INTERFACE:include>
)

# Qt模块链接
target_link_libraries(${LIB_NAME} PUBLIC
    Qt5::Core
    Qt5::Widgets
    Qt5::Qml
    Qt5::Quick
)

## 第三方依赖段
# VCPKG依赖查找
find_package(ZLIB REQUIRED)
find_package(OpenSSL REQUIRED)

# 自定义查找模块
include(cmake/FindAdvancedDeps.cmake)

target_link_libraries(${LIB_NAME} PRIVATE
    ZLIB::ZLIB
    OpenSSL::SSL
    ${ADVANCED_DEPS_LIBRARIES}
)

## 安装配置段
install(TARGETS ${LIB_NAME}
    EXPORT ${LIB_NAME}Targets
    ARCHIVE DESTINATION lib
    LIBRARY DESTINATION lib
    RUNTIME DESTINATION bin
    INCLUDES DESTINATION include
)

install(DIRECTORY include/
    DESTINATION include
    FILES_MATCHING PATTERN "*.h"
)

install(FILES
    ${TS_FILES}
    DESTINATION share/${LIB_NAME}/translations
)

# 导出配置
install(EXPORT ${LIB_NAME}Targets
    FILE ${LIB_NAME}Targets.cmake
    NAMESPACE ${LIB_NAME}::
    DESTINATION lib/cmake/${LIB_NAME}
)

include(CMakePackageConfigHelpers)
configure_package_config_file(
    cmake/${LIB_NAME}Config.cmake.in
    ${CMAKE_CURRENT_BINARY_DIR}/${LIB_NAME}Config.cmake
    INSTALL_DESTINATION lib/cmake/${LIB_NAME}
)

write_basic_package_version_file(
    ${CMAKE_CURRENT_BINARY_DIR}/${LIB_NAME}ConfigVersion.cmake
    VERSION ${PROJECT_VERSION}
    COMPATIBILITY SameMajorVersion
)

install(FILES
    ${CMAKE_CURRENT_BINARY_DIR}/${LIB_NAME}Config.cmake
    ${CMAKE_CURRENT_BINARY_DIR}/${LIB_NAME}ConfigVersion.cmake
    DESTINATION lib/cmake/${LIB_NAME}
)

## 高级功能段
# 单元测试
if(BUILD_TESTING)
    enable_testing()
    add_subdirectory(tests)
endif()

# 文档生成
if(BUILD_DOCS)
    find_package(Doxygen REQUIRED)
    add_custom_target(docs
        COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile
        WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/docs
        COMMENT "Generating API documentation"
    )
endif()

# 代码分析
if(ENABLE_CLANG_TIDY)
    find_program(CLANG_TIDY_EXE "clang-tidy")
    if(CLANG_TIDY_EXE)
        set(CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY_EXE}")
    endif()
endif()

3.2.2 命令解析

1.Windows符号导出:

set_target_properties(${LIB_NAME} PROPERTIES
    WINDOWS_EXPORT_ALL_SYMBOLS ON
)
  • 解决Windows平台DLL导出问题
  • 替代传统的__declspec(dllexport)手动标记

2.条件编译控制:

$<$<CONFIG:Debug>:d>
  • 生成器表达式实现Debug/Release后缀自动添加
  • 保持不同配置下的输出文件名区分

3.国际化支持:

qt5_add_translation(QM_FILES ${TS_FILES})
add_custom_target(translations ALL DEPENDS ${QM_FILES})
  • 完整的翻译文件处理流程
  • 集成Qt Linguist工具链

4.目标导出配置:

install(EXPORT ${LIB_NAME}Targets
    FILE ${LIB_NAME}Targets.cmake
    NAMESPACE ${LIB_NAME}::
    DESTINATION lib/cmake/${LIB_NAME}
)
  • 创建可导入的CMake配置
  • 支持find_package(${LIB_NAME})的使用方式

5.版本兼容性控制:

write_basic_package_version_file(
    ${LIB_NAME}ConfigVersion.cmake
    VERSION ${PROJECT_VERSION}
    COMPATIBILITY SameMajorVersion
)
  • 语义化版本控制
  • 主版本号相同的版本自动兼容

6.VCPKG集成优化:

if(DEFINED ENV{VCPKG_ROOT})
    set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake")
endif()
  • 自动检测环境变量配置
  • 避免硬编码路径

7.自定义查找模块:

include(cmake/FindAdvancedDeps.cmake)
target_link_libraries(${LIB_NAME} PRIVATE ${ADVANCED_DEPS_LIBRARIES})
  • 模块化组织复杂依赖
  • 保持主CMakeLists.txt的简洁性
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇