CMake 使用完整指南

2

一、CMake 简介

CMake 是一个跨平台的自动化构建工具,通过编写 CMakeLists.txt 文件描述项目构建规则,可生成不同平台(如 Linux/Makefile、Windows/Visual Studio)的本地构建文件。核心优势:

  • 跨平台:支持 Windows、Linux、macOS
  • 简化构建流程:自动处理依赖关系
  • 模块化管理:支持大型项目结构

二、安装 CMake

Linux

# Ubuntu/Debian
sudo apt install cmake

# CentOS
sudo yum install cmake

Windows

  1. 访问 CMake官网 下载安装包
  2. 安装时勾选 "Add to PATH"
  3. 验证安装:
cmake --version

三、基础用法

1. 最小化项目

项目结构:

project/
├── main.c
└── CMakeLists.txt

CMakeLists.txt:

cmake_minimum_required(VERSION 3.10)
project(MyProject)
add_executable(myapp main.c)

构建步骤:

mkdir build && cd build
cmake ..
make

2. 多源文件项目

# 手动指定文件
add_executable(app main.cpp utils.cpp)

# 自动收集源文件
file(GLOB SOURCES "src/*.cpp")
add_executable(app ${SOURCES})

3. 包含头文件目录

include_directories(include)  # 添加头文件搜索路径
target_include_directories(app PUBLIC include)  # 更推荐的方式

四、进阶场景

1. 生成静态库/动态库

生成静态库:

add_library(mylib STATIC src/mylib.cpp)

生成动态库:

add_library(mylib SHARED src/mylib.cpp)

2. 链接库文件

# 链接系统库
target_link_libraries(app PUBLIC pthread)

# 链接自定义库
add_subdirectory(lib)  # 包含子目录
target_link_libraries(app PUBLIC mylib)

3. 多目录项目结构

项目结构:

project/
├── CMakeLists.txt
├── src/
│   └── main.cpp
└── lib/
    ├── CMakeLists.txt
    ├── include/
    │   └── mylib.h
    └── src/
        └── mylib.cpp

根目录 CMakeLists.txt:

cmake_minimum_required(VERSION 3.10)
project(MyProject)
add_subdirectory(lib)
add_executable(app src/main.cpp)
target_link_libraries(app PUBLIC mylib)

lib/CMakeLists.txt:

add_library(mylib STATIC src/mylib.cpp)
target_include_directories(mylib PUBLIC include)

五、高级功能

1. 条件编译

option(USE_OPENMP "Enable OpenMP support" ON)

if(USE_OPENMP)
    find_package(OpenMP REQUIRED)
    target_link_libraries(app PUBLIC OpenMP::OpenMP_CXX)
endif()

2. 添加编译选项

target_compile_options(app PRIVATE -Wall -Wextra)

3. 生成配置文件

configure_file(config.h.in config.h)

config.h.in:

#define VERSION_MAJOR @PROJECT_VERSION_MAJOR@
#define VERSION_MINOR @PROJECT_VERSION_MINOR@

六、最佳实践

  1. 外部构建:始终在 build 目录执行构建
  2. 避免全局设置:优先使用 target_xxx 命令
  3. 版本管理
set(MyProject_VERSION_MAJOR 1)
set(MyProject_VERSION_MINOR 0)
  1. 跨平台处理
if(WIN32)
    # Windows 特定设置
elseif(UNIX)
    # Linux 特定设置
endif()

七、常用命令速查

命令功能
project()定义项目名称
add_executable()创建可执行文件
add_library()创建库文件
target_link_libraries()链接库文件
find_package()查找外部依赖
install()定义安装规则

八、参考资源

通过本指南,您可快速掌握从简单项目到复杂工程构建的CMake使用技巧。建议结合实践项目加深理解!

参考资料:
[1] https://blog.csdn.net/iuu77/article/details/129229361
[2] https://zhuanlan.zhihu.com/p/534439206
[3] https://zhuanlan.zhihu.com/p/500002865
[4] http://www.360doc.cn/article/9008018_296357404.html
[5] https://zhuanlan.zhihu.com/p/640680428
[6] https://m.blog.csdn.net/ZBraveHeart/article/details/132736292
[7] https://developer.aliyun.com/article/309821
[8] https://m.blog.csdn.net/az44yao/article/details/144727273
[9] https://m.blog.csdn.net/KgCrystal/article/details/133569398
[10] https://zhuanlan.zhihu.com/p/720220887
[11] https://blog.csdn.net/gitblog_06679/article/details/143333724
[12] https://blog.csdn.net/qq_41375609/article/details/110535697
[13] https://www.runoob.com/cmake/cmake-tutorial.html

直接回答

  • CMake 是一个跨平台的构建系统,用于管理 C++ 项目的编译和构建。
  • 它通过 CMakeLists.txt 文件生成适合不同平台的本地构建文件,如 Unix 的 Makefile 或 Windows 的 Visual Studio 项目文件。
  • 它支持跨平台构建、测试和打包,适合团队协作和多平台开发。

安装与设置

CMake 可从 cmake.org/download 下载,适用于 Windows、macOS 和 Linux。安装后,运行 cmake --version 检查版本。

基本使用

创建一个简单项目:

  1. 编写 main.cpp

    #include <iostream>
    int main() { std::cout << "Hello, World!" << std::endl; return 0; }
    
  2. 创建 CMakeLists.txt

    cmake_minimum_required(VERSION 3.20)
    project(MyProject)
    add_executable(myapp main.cpp)
    
  3. 构建:mkdir build; cd build; cmake ..; make; ./myapp

意外细节

CMake 不仅限于 C++,还支持其他语言,如 C 和 Python,增加了其灵活性。


详细报告

CMake 是一个强大的开源工具,广泛用于管理软件的构建、测试和打包过程,尤其在 C++ 项目中。它通过生成适合不同平台的本地构建文件(如 Makefile、Visual Studio 项目文件或 Ninja 文件),确保跨平台兼容性。以下是关于 CMake 使用的全面指南,涵盖从安装到高级主题的各个方面。

引言

什么是 CMake?
CMake 是一个跨平台的构建系统,允许开发者通过 CMakeLists.txt 文件定义软件的构建方式。它生成本地构建文件,适应不同的操作系统和开发环境,如 Unix 的 Makefile、Windows 的 Visual Studio 项目文件或 macOS 的 Xcode 项目文件。

为什么使用 CMake?

  • 跨平台兼容性:CMake 支持在 Windows、macOS 和 Linux 上生成本地构建文件,方便在不同平台上构建项目。
  • 一致的构建过程:通过单一配置文件,团队可以轻松共享和维护构建设置,减少平台差异带来的问题。
  • 易于协作:适合大型团队开发,确保所有成员使用相同的构建流程。
  • 扩展性:CMake 支持测试(通过 CTest)和打包(通过 CPack),提供完整的开发生命周期管理。

安装

CMake 的安装过程因平台而异,可从 cmake.org/download 获取最新版本。以下是各平台的安装步骤:

  • Windows

  • macOS

  • Linux

    • 使用包管理器安装,例如 Ubuntu 上运行 apt-get install cmake
    • 或下载源代码(如 cmake-3.31.6.tar.gz),解压并按照 README.rst 编译安装。

安装完成后,运行 cmake --version 检查版本,确保正确安装。

入门指南

为了帮助初学者快速上手,我们将创建一个简单的“Hello, World!” 项目。

  1. 创建项目目录

    • 在终端中运行:

      mkdir myproject
      cd myproject
      
  2. 编写源代码

    • 创建 main.cpp,内容如下:

      #include <iostream>
      int main() {
          std::cout << "Hello, World!" << std::endl;
          return 0;
      }
      
  3. 创建 CMakeLists.txt

    • 在项目目录下创建 CMakeLists.txt,内容如下:

      cmake_minimum_required(VERSION 3.20)
      project(MyProject)
      add_executable(myapp main.cpp)
      
    • cmake_minimum_required 指定所需的最低 CMake 版本。

    • project 定义项目名称。

    • add_executable 定义可执行目标 myapp,使用 main.cpp 作为源文件。

  4. 构建项目

    • 创建构建目录并导航:

      mkdir build
      cd build
      
    • 运行 CMake 生成构建文件:

      cmake ..
      
    • 根据生成器类型(默认 Unix Makefiles),运行构建命令:

      make
      
    • 运行可执行文件:

      ./myapp
      
    • 输出应为 “Hello, World!”。

对于 Windows 用户,可以指定 Visual Studio 生成器:

cmake -G "Visual Studio 16 2019" ..

然后使用 Visual Studio 打开生成的解决方案文件。

管理项目

在实际项目中,源文件通常分布在多个目录中,CMake 提供了灵活的方式来组织和管理这些文件。

  • 组织源文件

    • 使用 add_subdirectory 包含子目录。例如,项目结构如下:

      myproject/
      ├── src/
      │   ├── main.cpp
      │   └── helper.cpp
      └── CMakeLists.txt
      
    • 在根目录的 CMakeLists.txt 中添加:

      add_subdirectory(src)
      
    • src/CMakeLists.txt 中定义目标:

      add_executable(myapp main.cpp helper.cpp)
      
  • 定义目标

    • 可执行文件:使用 add_executable,如上例。

    • 库文件:使用 add_library 定义静态库或动态库。例如:

      add_library(mylib STATIC mylib.cpp)
      add_executable(myapp main.cpp)
      target_link_libraries(myapp mylib)
      
    • 库类型包括 STATIC(静态库)、SHARED(动态库)和 MODULE(模块库)。默认类型由 BUILD_SHARED_LIBS 变量控制。

  • 头文件和链接

    • 使用 include_directories 包含头文件目录,或更现代的方式使用 target_include_directories

      target_include_directories(mylib PUBLIC include)
      

以下是库和可执行文件的详细对比:

类型命令描述
可执行文件add_executable生成可运行程序,需指定源文件
静态库add_library(... STATIC)编译为 .a.lib 文件,链接时嵌入
动态库add_library(... SHARED)编译为 .so.dll 文件,运行时链接
模块库add_library(... MODULE)用于动态加载的插件,通常不直接链接

处理依赖

现代项目通常依赖外部库,CMake 提供了多种方式来管理这些依赖。

  • 查找系统库

    • 使用 find_package 查找已安装的系统库。例如,查找 Boost 库:

      find_package(Boost REQUIRED)
      include_directories(${Boost_INCLUDE_DIRS})
      target_link_libraries(myapp ${Boost_LIBRARIES})
      
    • find_package 支持模块模式(查找 Find<PackageName>.cmake)和配置模式(查找 <PackageName>Config.cmake)。默认先尝试模块模式,若失败则使用配置模式。

  • 使用外部库

    • 对于未安装的库,可以使用 FetchContent 下载并包含。例如,下载 Google Test:

      include(FetchContent)
      FetchContent_Declare(
        googletest
        GIT_REPOSITORY https://github.com/google/googletest
        GIT_TAG release-1.10.0
      )
      FetchContent_MakeAvailable(googletest)
      
    • FetchContent 在配置时下载内容,支持 Git、URL 等多种来源。

以下是依赖管理的常见方法对比:

方法适用场景优点缺点
find_package已安装的系统库或 CMake 支持的库简单,系统级支持,版本管理依赖系统安装,可能不适合自定义库
FetchContent未安装的库,需下载自动下载,适合开源库,版本可控增加构建时间,可能需要网络连接

构建配置

CMake 允许配置不同的构建类型(如 Debug、Release),并设置编译器标志。

  • 设置构建类型

    • 使用 CMAKE_BUILD_TYPE 变量,例如:

      set(CMAKE_BUILD_TYPE Debug)
      
    • 常见类型包括 Debug(调试模式,带调试信息)和 Release(发布模式,优化性能)。

  • 设置编译器标志

    • 使用 target_compile_options 设置目标特定的编译选项。例如:

      if(CMAKE_BUILD_TYPE MATCHES "Release")
          target_compile_options(myapp PRIVATE -O2 -Wall)
      else()
          target_compile_options(myapp PRIVATE -O0 -g)
      endif()
      
    • 也可以使用生成器表达式:

      target_compile_options(myapp PRIVATE "$<IF:$<CONFIG:Release>,-O2,-O0>")
      

测试与 CTest

测试是开发周期的重要部分,CMake 集成了 CTest 工具来运行和报告测试结果。

  • 启用测试

    • CMakeLists.txt 中添加:

      enable_testing()
      
  • 添加测试

    • 使用 add_test 定义测试。例如:

      add_executable(test_myapp test_main.cpp)
      add_test(NAME mytest COMMAND test_myapp)
      
  • 运行测试

    • 进入构建目录,运行:

      ctest
      
    • 可选参数包括 -V(详细输出)和 -R(运行匹配正则表达式的测试)。

CTest 支持任何返回退出码的命令,零表示成功,非零表示失败,适合 C++ 可执行文件、Python 脚本等。

打包与 CPack

CPack 是 CMake 提供的打包工具,支持生成多种格式的安装包,如 RPM、DEB、NSIS 等。

  • 设置 CPack

    • CMakeLists.txt 中添加:

      set(CPACK_GENERATOR "DEB")
      set(CPACK_DEBIAN_package_name "myapp")
      set(CPACK_DEBIAN_package_version "1.0")
      include(CPack)
      
  • 生成包

    • 运行:

      cpack
      
    • 生成的包文件(如 myapp_1.0.deb)位于构建目录下。

CPack 支持多种生成器,具体可用生成器可通过 cpack --help 查看。

以下是常见打包格式的对比:

格式平台描述
DEBLinux (Debian/Ubuntu)Debian 包,适合 Linux 发行版
RPMLinux (Red Hat)Red Hat 包,适合 RHEL/CentOS 系统
NSISWindowsWindows 安装程序,图形界面安装
DMGmacOSmacOS 磁盘镜像,适合 macOS 应用分发

高级主题

对于复杂项目,CMake 提供了许多高级功能。

  • 自定义命令和目标

    • 使用 add_custom_command 定义构建过程中的自定义命令。例如:

      add_custom_command(TARGET myapp PRE_BUILD
                         COMMAND script.sh
                         COMMENT "Running script"
                         VERBATIM)
      
    • configure_file 用于生成文件:

      configure_file(input.txt output.txt @ONLY)
      
  • 生成器表达式

    • 用于条件设置属性。例如:

      target_link_options(myapp PRIVATE "$<IF:$<CONFIG:Debug>,-Wl,--verbose,-v,-Wl,--verbose,-v,>")
      
    • 支持根据配置(Debug/Release)、平台等动态调整构建规则。

  • 交叉编译

    • 通过工具链文件定义目标平台。例如:

      set(CMAKE_SYSTEM_NAME Linux)
      set(CMAKE_C_COMPILER arm-linux-gcc)
      set(CMAKE_CXX_COMPILER arm-linux-g++)
      
    • 运行 CMake 时指定工具链文件:

      cmake -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake ..
      
  • 平台特定配置

    • 使用条件语句根据平台设置不同选项。例如:

      if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
          # Windows 特定设置
      else()
          # 其他平台
      endif()
      

最佳实践

为了保持 CMake 代码的整洁和可维护性,建议遵循以下最佳实践:

  • 保持整洁:将 CMakeLists.txt 分割为多个文件,使用 add_subdirectory 组织大型项目。
  • 避免重复:使用函数和宏(如 functionmacro)封装重复逻辑。
  • 文档化:在 CMake 文件中添加注释,说明复杂逻辑。
  • 跨平台测试:在不同平台上测试构建系统,确保兼容性。
  • 版本控制:将 CMakeLists.txt 纳入版本控制系统(如 Git),跟踪更改。

资源

以下是进一步学习的资源:

关键引用