CMake 完全指南:第二章 - CMake初体验 - Hello, CMake World!

175 阅读9分钟

一、 环境准备:确认CMake已就位

在开始“施法”之前,确保你的“魔杖”(CMake)已经安装并可用。

  1. 打开命令行终端:

    • Windows: Win+R -> 输入 cmd 或 powershell -> 回车。
    • Linux/macOS: 打开 Terminal
  2. 验证CMake安装:
    在命令行中输入以下命令并按回车:

    cmake --version
    
  3. 期望结果:
    你应该看到类似以下的输出,显示CMake的版本信息(你的版本号可能更高):

    cmake version 3.28.3
    CMake suite maintained and supported by Kitware (kitware.com/cmake).
    
    • 如果看到版本号:恭喜!  CMake已正确安装并配置在系统路径(PATH)中。你可以继续下一步。

    • 如果提示 'cmake' 不是内部或外部命令... 或 command not found

      • Windows:  检查安装时是否勾选了“Add CMake to the system PATH for all users”或“Add CMake to the current user's PATH”。如果没有,你需要手动将CMake的 bin 目录(例如 C:\Program Files\CMake\bin)添加到系统的PATH环境变量中,或者重新安装并勾选该选项。也可以在安装目录下的 bin 文件夹中打开命令行。
      • Linux/macOS:  确保你使用了正确的包管理器命令安装(如 sudo apt install cmake for Ubuntu/Debian, brew install cmake for macOS)。如果已安装但不在PATH中,检查安装路径(通常 /usr/bin 或 /usr/local/bin)是否在PATH中。

二、 创建项目:最简单的结构

我们将创建一个极其简单的项目,只包含两个文件:一个C++源文件和一个CMake的“配方”文件。

  1. 创建项目目录:
    在命令行中,导航到你想要创建项目的父目录。然后创建一个新目录并进入它:

    mkdir cmake-hello-world  # 创建项目根目录
    cd cmake-hello-world     # 进入项目根目录
    
  2. 创建源代码文件 (main.cpp):
    使用你喜欢的文本编辑器(VS Code, Notepad++, Vim, Nano等)在 cmake-hello-world 目录下创建一个名为 main.cpp 的文件。

  3. 编辑 main.cpp 内容:
    将以下经典的C++代码复制进去:

    #include <iostream>
    
    int main() {
        std::cout << "Hello, CMake World!" << std::endl;
        return 0;
    }
    

    保存文件。这个文件就是我们要编译的程序源代码。

  4. 创建CMake的“配方”文件 (CMakeLists.txt):
    同一个目录 (cmake-hello-world) 下,使用文本编辑器创建一个名为 CMakeLists.txt 的文件(注意大小写和没有后缀!  CMakeLists.txt 是固定文件名)。

  5. 编辑 CMakeLists.txt 内容:
    将以下内容复制进去:

    # 设置CMake所需的最低版本 (强烈推荐)
    cmake_minimum_required(VERSION 3.10)
    
    # 定义项目名称 (这里叫 "HelloCMake") 和使用的编程语言 (CXX代表C++)
    project(HelloCMake LANGUAGES CXX)
    
    # 添加一个可执行文件目标 (Target)
    # 目标名: HelloCMakeApp
    # 构建它所需的源文件: main.cpp
    add_executable(HelloCMakeApp main.cpp)
    

    逐行解释:

    • # 设置CMake所需的最低版本 (强烈推荐)

      • # 表示注释,CMake会忽略它。用于解释代码。
    • cmake_minimum_required(VERSION 3.10)

      • 作用:  指定运行此CMakeLists.txt文件所需的最低CMake版本。这是一个强制的、良好的实践。它确保用户使用的CMake版本满足项目需求,并影响CMake的策略行为(处理兼容性问题)。我们这里要求至少3.10(一个相对较新且广泛支持的版本)。请根据你的实际环境调整(但3.10+通常安全)。
    • # 定义项目名称...

    • project(HelloCMake LANGUAGES CXX)

      • 作用:  定义项目的名称和使用的编程语言。
      • HelloCMake:这是你给项目起的名字。它会设置一些有用的变量(如 PROJECT_NAME)。
      • LANGUAGES CXX:明确指定项目的主要编程语言是C++ (CXX 是CMake中C++的标识符)。如果你的项目有C代码,可以写 C CXX。这个命令必须在 cmake_minimum_required 之后调用。
    • # 添加一个可执行文件目标...

    • add_executable(HelloCMakeApp main.cpp)

      • 核心作用:  告诉CMake,你想要构建一个名为 HelloCMakeApp 的可执行文件
      • HelloCMakeApp:这是你给这个可执行文件目标(Target)  起的名字。这个名字将用于后续的构建步骤和可能的链接。
      • main.cpp:这是构建这个可执行文件所需的一个源文件。如果项目有多个源文件,可以在这里列出(例如 add_executable(MyApp main.cpp utils.cpp))。这是现代CMake最基本也是最重要的命令之一。

三、 经典构建流程:生成 + 构建

CMake的构建流程通常分为两步,并且强烈推荐在一个独立的构建目录(build)中进行(称为“out-of-source build”)。这样做的好处是:保持源代码目录干净,避免生成的构建文件污染源码;方便为不同配置(如Debug/Release)或不同平台创建独立的构建目录。

  1. 创建并进入构建目录 (build):
    在项目根目录 (cmake-hello-world) 下执行:

    mkdir build   # 创建名为 build 的子目录
    cd build      # 进入 build 目录
    
    • 现在你的目录结构应该是:

      cmake-hello-world/
      ├── CMakeLists.txt
      ├── main.cpp
      └── build/       <-- 你现在在这里 (cd build)
      
  2. 运行CMake生成构建系统 (Generate):
    在 build 目录中,运行以下命令:

    cmake ..
    
    • cmake:  调用CMake程序。

    • ..:  关键参数!  这告诉CMake:包含 CMakeLists.txt 文件的源代码目录在当前位置的上一级目录(即 cmake-hello-world)。CMake会去 .. 目录下寻找 CMakeLists.txt

    • 按下回车,见证魔法开始!

    • 期望输出(Linux/macOS 使用 Makefile 示例):

      -- The CXX compiler identification is GNU 11.4.0 / AppleClang 15.0.0 / etc.
      -- Detecting CXX compiler ABI info
      -- Detecting CXX compiler ABI info - done
      -- Check for working CXX compiler: /usr/bin/c++ - skipped
      -- Detecting CXX compile features
      -- Detecting CXX compile features - done
      -- Configuring done (X.Xs)
      -- Generating done (X.Xs)
      -- Build files have been written to: /path/to/cmake-hello-world/build
      
    • 期望输出(Windows 使用 Visual Studio Generator 示例):

      -- Selecting Windows SDK version 10.0.20348.0 to target Windows 10.0.22631.
      -- The CXX compiler identification is MSVC 19.38.33133.0
      -- Detecting CXX compiler ABI info
      -- Detecting CXX compiler ABI info - done
      -- Check for working CXX compiler: C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.38.33130/bin/Hostx64/x64/cl.exe - skipped
      -- Detecting CXX compile features
      -- Detecting CXX compile features - done
      -- Configuring done (X.Xs)
      -- Generating done (X.Xs)
      -- Build files have been written to: C:/path/to/cmake-hello-world/build
      
    • 发生了什么?

      • CMake 读取了上一级目录 (..) 中的 CMakeLists.txt 文件。

      • 检测了你的系统环境(操作系统、可用的C++编译器)。

      • 它根据 CMakeLists.txt 的描述和检测到的环境,在当前目录 (build)  下生成了对应平台的本地构建系统文件

        • 在 Linux/macOS 上,默认生成的是 Makefile
        • 在 Windows 上,如果安装了Visual Studio,默认可能生成 HelloCMake.sln (解决方案文件) 和相关的 .vcxproj (项目文件)。也可能生成 Makefile (如果安装了MinGW) 或 build.ninja
      • 查看一下你的 build 目录,是不是多了很多文件?这就是生成的构建系统文件。

  3. 使用生成的构建系统进行编译链接 (Build):
    生成了构建系统文件后,就可以使用它们来实际编译和链接你的程序了。CMake 提供了一个统一的命令来完成这一步:

    cmake --build .
    
    • cmake --build .:  这个命令告诉CMake: “请调用当前目录 (.) 下由我生成的本地构建系统,执行实际的构建任务(编译和链接)。”

    • 按下回车,编译器开始工作!

    • 期望输出(简化示例):

      [ 50%] Building CXX object CMakeFiles/HelloCMakeApp.dir/main.cpp.o
      [100%] Linking CXX executable HelloCMakeApp
      [100%] Built target HelloCMakeApp
      
      • 第一行:编译器 (g++clang++cl.exe) 正在编译 main.cpp 文件,生成 main.cpp.o (或 main.obj on Windows) 对象文件。
      • 第二行:链接器 (ldlink.exe) 正在将对象文件链接成最终的可执行文件 HelloCMakeApp (或 HelloCMakeApp.exe on Windows)。
      • 第三行:恭喜!构建目标 HelloCMakeApp 已成功构建完成!
    • 发生了什么?

      • cmake --build . 没有直接调用编译器 (g++/cl),而是调用了CMake在 build 目录生成的本地构建系统
      • 在 Linux/macOS (生成了 Makefile 的情况下),cmake --build . 内部相当于执行了 make
      • 在 Windows (生成了 Visual Studio 解决方案的情况下),cmake --build . 内部相当于执行了 MSBuild HelloCMake.sln 或启动了Visual Studio的构建过程。
      • 本地构建系统负责了依赖检查、增量编译(只编译改动过的文件)、并行编译(如果支持)等所有繁琐细节。
  4. 找到并运行你的程序:
    构建成功后,可执行文件 HelloCMakeApp (或 HelloCMakeApp.exe) 应该就生成在 build 目录(或者其子目录,如 Debug/Release,具体取决于生成器和配置,但通常就在 build 根目录)。

    • Linux/macOS:

      ./HelloCMakeApp
      

      输出:

      Hello, CMake World!
      
    • Windows (CMD):

      cmd

      HelloCMakeApp.exe
      

      输出:

      Hello, CMake World!
      
    • Windows (PowerShell):

      .\HelloCMakeApp.exe
      

      输出:

      Hello, CMake World!
      
    • 你成功使用CMake构建并运行了你的第一个程序!这就是自动化构建的力量。

四、 核心流程回顾与理解

让我们再清晰地梳理一下整个过程的两个核心步骤及其作用:

  1. cmake <path-to-source> (这里是 cmake ..):

    • 角色:  配置 (Configure) 和 生成 (Generate)  阶段。
    • 输入:  你的源代码目录 (包含 CMakeLists.txt 和 .cpp 文件)。
    • 输出:  在指定的构建目录 (build) 中生成特定于当前平台和编译器本地构建系统文件 (Makefile.sln/.vcxprojbuild.ninja 等)。
    • 关键点:  这个步骤不编译代码!它只根据你的项目描述 (CMakeLists.txt) 和当前环境,生成了后续真正用来编译的“蓝图”或“脚本”(即本地构建系统文件)。如果修改了 CMakeLists.txt 或添加/删除了源文件,必须重新运行 cmake (或 cmake .. 如果还在build目录) 来重新生成构建系统文件,使其包含最新更改。有时环境变化(如安装了新库)也需要重新运行。
  2. cmake --build <path-to-build> (这里是 cmake --build .):

    • 角色:  构建 (Build)  阶段。
    • 输入:  上一步生成的本地构建系统文件(位于构建目录 build)。
    • 输出:  编译链接生成最终的可执行文件或库文件。
    • 关键点:  这个步骤实际调用编译器 (g++clang++cl.exe) 和链接器。它利用本地构建系统来智能地管理编译过程(依赖、增量、并行)。如果你只修改了 .cpp 文件而没有改动 CMakeLists.txt 或项目结构,通常只需重新运行 cmake --build .  就能高效地重新编译。

五、 本章小结

在本章,你完成了CMake旅程中激动人心的第一步:

  1. 环境确认:  使用 cmake --version 验证安装。

  2. 项目创建:  建立了包含 main.cpp (源代码) 和 CMakeLists.txt (项目描述) 的最小项目结构。

  3. 编写配方:  理解了第一个 CMakeLists.txt 中的核心命令:

    • cmake_minimum_required:设置最低CMake版本。
    • project:定义项目名称和语言。
    • add_executable:声明要构建的可执行文件目标及其源文件。
  4. 执行经典流程:

    • mkdir build && cd build强烈推荐使用独立的构建目录 (out-of-source build)。
    • cmake ..生成针对当前平台的本地构建系统文件。
    • cmake --build .调用生成的构建系统实际编译链接你的程序。
  5. 运行成果:  成功在命令行中运行了 HelloCMakeApp,看到了 Hello, CMake World! 的输出。

  6. 理解核心:  明确了CMake工作的两阶段模型生成 (Generate)  和 构建 (Build)