Skip to content

CMake 基础教程

CMake 是一个跨平台的自动化构建系统工具,广泛应用于大型和跨平台的 C++ 项目中。以下是对 CMake 的所有功能和方法的详细解释。

1. CMake 基础功能

1.1 项目定义和配置

  • cmake_minimum_required(VERSION <version>)

    • 该命令用于指定项目所需的最低 CMake 版本。例如,cmake_minimum_required(VERSION 3.10) 表示要求 CMake 版本至少为 3.10。此命令确保使用的 CMake 版本具有你所需的功能或特性。
  • project(<project_name> [<language>...])

    • 该命令用于定义项目的名称。你可以指定项目使用的语言(如 CXX 代表 C++,C 代表 C 语言等)。如果没有指定语言,CMake 会默认使用 C 语言。
    cmake
    project(MyProject CXX)
  • set(<variable> <value>)

    • 该命令用于设置一个变量的值。例如,set(SRC_FILES main.cpp) 会将 main.cpp 存储在 SRC_FILES 变量中,可以在后续命令中使用。
    • 也可以设置路径或其他选项。比如:
    cmake
    set(CMAKE_CXX_STANDARD 11)

    这行代码会将 C++ 标准设置为 C++11。

1.2 构建目标

  • add_executable(<name> <source_files>)

    • 定义一个可执行目标文件。例如,add_executable(MyApp main.cpp) 会创建一个名为 MyApp 的可执行文件,将 main.cpp 作为源文件。
  • add_library(<name> <source_files>)

    • 定义一个库目标,可以是静态库(默认)或共享库(通过 SHARED 选项指定)。例如:
    cmake
    add_library(MyLibrary STATIC mylib.cpp)

    这会生成一个静态库 MyLibrary.a,并将 mylib.cpp 文件作为源文件。

  • target_link_libraries(<target> <libraries>)

    • 用于为目标链接外部库。比如:
    cmake
    target_link_libraries(MyApp MyLibrary)

    MyAppMyLibrary 静态库进行链接。

2. 变量操作和条件判断

2.1 变量操作

  • set(<variable> <value>)

    • 设置一个变量的值,如:
    cmake
    set(SOURCE_FILES main.cpp utils.cpp)
  • get_filename_component(<variable> <filename> <option>)

    • 从文件路径中提取信息(如文件名、目录、扩展名等)。常见选项包括:
      • NAME 提取文件名
      • DIRECTORY 提取目录路径
      • EXT 提取文件扩展名
    cmake
    get_filename_component(DIR_PATH /path/to/file.cpp DIRECTORY)
  • list(<command> <args>)

    • 对列表变量进行操作,如查找、排序、添加或删除元素:
    cmake
    list(APPEND SRC_FILES newfile.cpp)
    list(SORT SRC_FILES)

2.2 条件判断

  • if(<condition>) ... else() ... endif()

    • 用于执行条件判断:
    cmake
    if(WIN32)
        message(STATUS "This is Windows")
    elseif(APPLE)
        message(STATUS "This is macOS")
    else()
        message(STATUS "This is Linux")
    endif()
  • elseif(<condition>)

    • 用于多重条件判断。可与 if 配合使用。
  • else()

    • 用于 if 语句的备选代码块。

2.3 循环

  • foreach(<loop_variable> <values>) ... endforeach()

    • 用于遍历一个列表的所有元素:
    cmake
    foreach(file IN LISTS SRC_FILES)
        message(STATUS "Processing ${file}")
    endforeach()

3. 查找和使用外部库

3.1 查找外部包

  • find_package(<package_name> [version] [REQUIRED|OPTIONAL])

    • 查找并引入外部依赖包。常用的包有 Boost、OpenCV 等。
    • REQUIRED 表示包为必需项,若找不到则会抛出错误;OPTIONAL 表示包为可选项。
    cmake
    find_package(OpenCV REQUIRED)

3.2 目标链接

  • target_link_libraries(<target> <library>)

    • 用于将外部库链接到指定目标。例如:
    cmake
    target_link_libraries(MyApp Boost::Boost)

3.3 头文件和源文件

  • include_directories(<directory>)

    • 将头文件目录添加到目标的编译路径中。例如:
    cmake
    include_directories(${CMAKE_SOURCE_DIR}/include)
  • file(<command> <args>)

    • 进行文件操作,如查找文件、读取文件内容等:
    cmake
    file(GLOB SRC_FILES "*.cpp")

4. 构建选项和配置

4.1 选项和开关

  • option(<option_name> <description> <initial_value>)

    • 设置一个布尔值选项,可以通过命令行或 CMake GUI 来启用或禁用功能。例如:
    cmake
    option(USE_OPENMP "Use OpenMP" ON)

4.2 编译选项

  • add_compile_options(<options>)

    • 为所有目标添加编译选项。例如,添加优化选项:
    cmake
    add_compile_options(-O2)
  • target_compile_options(<target> <PRIVATE|PUBLIC> <options>)

    • 为指定目标添加编译选项:
    cmake
    target_compile_options(MyApp PRIVATE -Wall)

4.3 链接选项

  • add_link_options(<options>)

    • 为所有目标添加链接选项,例如添加链接器优化选项:
    cmake
    add_link_options(-O2)
  • target_link_options(<target> <options>)

    • 为指定目标添加链接选项:
    cmake
    target_link_options(MyApp PRIVATE -L/path/to/lib)

5. CMake 构建功能

5.1 构建系统生成

  • cmake ..
    • 从构建目录运行 CMake,指定源目录并生成构建文件(如 Makefile)。
  • cmake --build .
    • 使用生成的构建文件进行实际的编译和链接。

5.2 并行构建

  • cmake --build . -- -jN
    • 使用 N 个核心进行并行构建。例如,-j4 会使用 4 核进行并行构建。

5.3 安装功能

  • install(TARGETS <target> DESTINATION <path>)

    • 安装构建好的目标文件到指定路径:
    cmake
    install(TARGETS MyApp DESTINATION /usr/local/bin)
  • install(FILES <files> DESTINATION <path>)

    • 安装指定的文件(如头文件或配置文件)。

5.4 测试功能

  • enable_testing()

    • 启用测试功能。
  • add_test(NAME <test_name> COMMAND <test_command>)

    • 添加一个测试:
    cmake
    add_test(NAME MyTest COMMAND my_test_executable)
  • ctest

    • 执行测试,显示测试结果。

6. 调试和日志

6.1 调试信息

  • message(<message_type> <message>)

    • 打印信息到终端。可以选择不同的消息类型:
    • STATUS 打印普通信息
    • WARNING 打印警告
    • ERROR 打印错误并停止 CMake 过程
    cmake
    message(STATUS "Building ${PROJECT_NAME}")

6.2 日志记录

  • file(WRITE <filename> <content>)

    • 将内容写入指定文件:
    cmake
    file(WRITE "${CMAKE_BINARY_DIR}/log.txt" "Build started")

7. 高级功能

7.1 生成器表达式

  • $<...>

    • CMake 支持生成器表达式,用于在构建过程中动态生成特定的值。例如:
    cmake
    target_compile_definitions(MyApp PRIVATE $<CONFIG:Debug>)

7.2 交叉编译

  • CMAKE_TOOLCHAIN_FILE
    • 用于指定交叉编译工具链配置文件,适用于不同平台或架构的编译过程。

7.3 模块和包管理

  • include(<module_name>)

    • 包含 CMake 模块或脚本,用于扩展 CMake 的功能:
    cmake
    include(CMakeFindPackageHelper)

8. 跨平台支持

8.1 平台检查

  • if(WIN32)

    • 检查当前构建环境是否为 Windows 平台。
  • if(APPLE)

    • 检查当前构建环境是否为 macOS 平台。
  • if(UNIX)

    • 检查当前构建环境是否为 Unix-like 平台(如 Linux)。

8.2 平台特定设置

  • set(CMAKE_OSX_ARCHITECTURES "x86_64")
    • 设置 macOS 的架构。

9. 跨项目集成

9.1 导出配置

  • export(TARGETS <target> FILE <file>)
    • 将构建的目标导出到配置文件,供其他项目使用。
  • install(EXPORT <export_name> DESTINATION <dir>)
    • 导出目标配置,供其他项目通过 find_package 查找和使用。

10. CMake 与 IDE 集成

CMake 可以与多种 IDE (如 CLion、Visual Studio、Xcode)集成,自动生成适用于目标平台的工程文件。通过 CMake 配置的项目能够方便地在不同平台上构建。


通过掌握这些命令和功能,CMake 可以帮助开发者更高效地管理项目的构建过程,支持跨平台开发和复杂的依赖关系管理。

Released under the MIT License.