用户交互指南

简介

当软件包提供基于 CMake 的构建系统与其软件源代码一起时,软件的消费者需要运行 CMake 用户交互工具来构建它。

行为良好的基于 CMake 的构建系统不会在源代码目录中产生任何输出,因此通常,用户会执行“out-of-source”构建并在那里执行构建。首先,必须指示 CMake 生成合适的构建系统,然后用户调用构建工具来处理该生成的构建系统。生成的构建系统特定于用于生成它的机器,不可重新分发。提供的源代码软件包的每个消费者都需要使用 CMake 来生成特定于其系统的构建系统。

生成的构建系统通常应被视为只读。CMake 文件作为主要产物应完全指定构建系统,并且在生成构建系统后,例如在 IDE 中手动填充属性没有理由。CMake 会定期重写生成的构建系统,因此用户的手动修改将被覆盖。

本手册中描述的功能和用户界面通过提供 CMake 文件,可用于所有基于 CMake 的构建系统。

CMake 工具在处理提供的 CMake 文件时可能会向用户报告错误,例如报告编译器不受支持,或编译器不支持必需的编译选项,或找不到依赖项。这些错误必须由用户通过选择不同的编译器,安装依赖项,或指示 CMake 在哪里找到它们来解决,等等。

命令行 cmake 工具

简单但典型的用法是,使用 cmake(1) 处理软件的源代码的全新副本,创建一个构建目录并在那里调用 cmake。

$ cd some_software-1.4.2
$ mkdir build
$ cd build
$ cmake .. -DCMAKE_INSTALL_PREFIX=/opt/the/prefix
$ cmake --build .
$ cmake --build . --target install

建议在独立于源代码的目录中进行构建,因为这可以使源代码目录保持整洁,允许使用多种工具链构建单个源,并允许通过简单地删除构建目录来轻松清除构建产物。

CMake 工具可能会报告一些警告,这些警告是为软件提供者准备的,而不是为软件消费者准备的。此类警告的结尾是“此警告是为项目开发人员准备的”。用户可以通过将 -Wno-dev 标志传递给 cmake(1) 来禁用这些警告。

cmake-gui 工具

更习惯 GUI 界面的用户可以使用 cmake-gui(1) 工具来调用 CMake 并生成构建系统。

必须首先填充源目录和二进制目录。始终建议将源目录和构建目录分开使用。

Choosing source and binary directories

生成构建系统

有几种用户界面工具可用于从 CMake 文件生成构建系统。 ccmake(1)cmake-gui(1) 工具指导用户设置各种必要的选项。 cmake(1) 工具可以被调用以在命令行上指定选项。本手册描述了可以使用任何用户界面工具设置的选项,尽管设置选项的方式因工具而异。

命令行环境

当使用 MakefilesNinja 等命令行构建系统调用 cmake(1) 时,有必要使用正确的构建环境以确保构建工具可用。CMake 必须能够找到适当的 构建工具、编译器、链接器和其他所需工具。

在 Linux 系统上,适当的工具通常位于系统范围的位置,并且可以通过系统包管理器轻松安装。用户提供或安装在非默认位置的其他工具链也可以使用。

在交叉编译时,某些平台可能需要设置环境变量,或者可能提供用于设置环境的脚本。

Visual Studio 提供了多个命令行提示符和 vcvarsall.bat 脚本,用于为命令行构建系统设置正确的环境。虽然在使用 Visual Studio 生成器时并非必须使用相应的命令行环境,但这没有任何缺点。

使用 Xcode 时,可能安装了多个 Xcode 版本。可以使用多种方式选择要使用的版本,但最常见的方法是:

  • 在 Xcode IDE 的首选项中设置默认版本。

  • 通过 xcode-select 命令行工具设置默认版本。

  • 在运行 CMake 和构建工具时,通过设置 DEVELOPER_DIR 环境变量来覆盖默认版本。

为了方便起见,cmake-gui(1) 提供了一个环境变量编辑器。

命令行 -G 选项

CMake 默认根据平台选择一个生成器。通常,默认生成器足以让用户继续构建软件。

用户可以使用 -G 选项覆盖默认生成器。

$ cmake .. -G Ninja

运行 cmake --help 的输出包含了用户可供选择的 生成器 列表。请注意,生成器名称区分大小写。

在类 Unix 系统(包括 Mac OS X)上,默认使用 Unix Makefiles 生成器。该生成器的变体也可用于 Windows 的各种环境中,例如 NMake MakefilesMinGW Makefiles 生成器。这些生成器生成一个 Makefile 变体,可以使用 makegmakenmake 或类似工具执行。有关目标环境和工具的更多信息,请参阅各个生成器文档。

Ninja 生成器在所有主要平台上都可用。ninja 是一个与 make 在用途上相似的构建工具,但侧重于性能和效率。

在 Windows 上,cmake(1) 可用于为 Visual Studio IDE 生成解决方案。可以通过 IDE 的产品名称指定 Visual Studio 版本,其中包含四位数字的年份。还提供了别名来指代有时用于引用 Visual Studio 版本的其他方式,例如对应于 VisualC++ 编译器产品版本的两位数字,或者两者的组合。

$ cmake .. -G "Visual Studio 2019"
$ cmake .. -G "Visual Studio 16"
$ cmake .. -G "Visual Studio 16 2019"

Visual Studio 生成器 可以定位不同的架构。可以使用 -A 选项指定目标架构。

cmake .. -G "Visual Studio 2019" -A x64
cmake .. -G "Visual Studio 16" -A ARM
cmake .. -G "Visual Studio 16 2019" -A ARM64

在 Apple 上,可以使用 Xcode 生成器来生成 Xcode IDE 的项目文件。

像 KDevelop4、QtCreator 和 CLion 这样的某些 IDE 对基于 CMake 的构建系统有本地支持。这些 IDE 提供了用户界面来选择底层使用的生成器,通常是在 MakefileNinja 基于的生成器之间进行选择。

请注意,在第一次调用 CMake 后,无法使用 -G 更改生成器。要更改生成器,必须删除构建目录并从头开始构建。

生成 Visual Studio 项目和解决方案文件时,在最初运行 cmake(1) 时还有其他选项可用。

可以使用 cmake -T 选项指定 Visual Studio 工具集。

$ # Build with the clang-cl toolset
$ cmake.exe .. -G "Visual Studio 16 2019" -A x64 -T ClangCL
$ # Build targeting Windows XP
$ cmake.exe .. -G "Visual Studio 16 2019" -A x64 -T v120_xp

虽然 -A 选项指定的是**目标**架构,但 -T 选项可用于指定工具链的详细信息。例如,可以给出 -Thost=x64 来选择 64 位版本的宿主工具。以下演示了如何使用 64 位工具并为 64 位目标架构进行构建。

$ cmake .. -G "Visual Studio 16 2019" -A x64 -Thost=x64

在 cmake-gui 中选择生成器

“Configure”按钮会触发一个新的对话框来选择要使用的 CMake 生成器。

Configuring a generator

命令行上可用的所有生成器也都可以用于 cmake-gui(1)

Choosing a generator

选择 Visual Studio 生成器时,还可以设置要为其生成的目标架构的更多选项。

Choosing an architecture for Visual Studio generators

设置构建变量

软件项目通常要求在调用 CMake 时在命令行上设置变量。下表列出了一些最常用的 CMake 变量。

变量

含义

CMAKE_PREFIX_PATH

搜索 依赖包 的路径

CMAKE_MODULE_PATH

搜索附加 CMake 模块的路径

CMAKE_BUILD_TYPE

构建配置,例如 DebugRelease,决定调试/优化标志。这仅与单配置构建系统相关,例如 Makefile 生成器Ninja 生成器。多配置构建系统,例如用于 Visual Studio 生成器Xcode 的系统会忽略此设置。

CMAKE_INSTALL_PREFIX

使用 install 构建目标安装软件的位置。

CMAKE_TOOLCHAIN_FILE

包含交叉编译数据的ファイル,例如 工具链和 sysroots

BUILD_SHARED_LIBS

对于不带类型使用的 add_library() 命令,是构建共享库还是静态库。

CMAKE_EXPORT_COMPILE_COMMANDS

生成 compile_commands.json 文件,供 clang 类工具使用。

CMAKE_EXPORT_BUILD_DATABASE

生成 build_database.json 文件,供 clang 类工具使用。

其他项目特定的变量可能可用于控制构建,例如启用或禁用项目的组件。

CMake 没有为不同提供程序之间如何命名这些变量提供约定,除了带有 CMAKE_ 前缀的变量通常指 CMake 本身提供的选项,不应在第三方选项中使用,第三方应使用自己的前缀。 cmake-gui(1) 工具可以按前缀定义的组显示选项,因此第三方确保使用一致的前缀是有意义的。

在命令行设置变量

CMake 变量可以在创建初始构建时在命令行上设置。

$ mkdir build
$ cd build
$ cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Debug

或在后续调用 cmake(1) 时设置。

$ cd build
$ cmake . -DCMAKE_BUILD_TYPE=Debug

-U 标志可用于在 cmake(1) 命令行上取消设置变量。

$ cd build
$ cmake . -UMyPackage_DIR

最初在命令行创建的 CMake 构建系统可以使用 cmake-gui(1) 修改,反之亦然。

cmake(1) 工具允许使用 -C 选项指定一个文件来填充初始缓存。这对于简化反复需要相同缓存条目的命令和脚本很有用。

使用 cmake-gui 设置变量

可以使用“Add Entry”按钮在 cmake-gui 中设置变量。这将触发一个新的对话框来设置变量的值。

Editing a cache entry

cmake-gui(1) 用户界面的主视图可用于编辑现有变量。

CMake 缓存

当 CMake 执行时,它需要找到编译器、工具和依赖项的位置。它还需要能够一致地重新生成构建系统以使用相同的编译/链接标志和依赖项路径。这些参数也需要由用户可配置,因为它们是特定于用户系统的路径和选项。

首次执行时,CMake 会在构建目录中生成一个 CMakeCache.txt 文件,其中包含此类工件的键值对。用户可以通过运行 cmake-gui(1)ccmake(1) 工具来查看或编辑缓存文件。这些工具提供了交互式界面,用于在编辑缓存值后重新配置提供的软件并重新生成构建系统。每个缓存条目可能都有一个相关的简短帮助文本,该文本显示在用户界面工具中。

缓存条目还可以有一个类型来指示它应该如何在用户界面中显示。例如,类型为 BOOL 的缓存条目可以通过用户界面中的复选框进行编辑,STRING 可以在文本字段中编辑,而 FILEPATH 虽然与 STRING 类似,但还应提供一种使用文件对话框查找文件系统路径的方法。类型为 STRING 的条目可以提供一个允许值的受限列表,然后这些值将出现在 cmake-gui(1) 用户界面中的下拉菜单中(请参阅 STRINGS 缓存属性)。

随软件包提供的 CMake 文件也可以使用 option() 命令定义布尔切换选项。该命令创建一个具有帮助文本和默认值的缓存条目。此类缓存条目通常特定于提供的软件,并影响构建的配置,例如是否构建测试和示例,是否启用异常构建等。

预设

CMake 理解一个文件 CMakePresets.json 及其用户特定对应文件 CMakeUserPresets.json,用于保存常用配置设置的预设。这些预设可以设置构建目录、生成器、缓存变量、环境变量和其他命令行选项。所有这些选项都可以被用户覆盖。 CMakePresets.json 格式的完整详细信息列在 cmake-presets(7) 手册中。

在命令行使用预设

使用 cmake(1) 命令行工具时,可以通过使用 --preset 选项调用预设。如果指定了 --preset,则不需要生成器和构建目录,但可以指定它们来覆盖它们。例如,如果您有以下 CMakePresets.json 文件:

{
  "version": 1,
  "configurePresets": [
    {
      "name": "ninja-release",
      "binaryDir": "${sourceDir}/build/${presetName}",
      "generator": "Ninja",
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Release"
      }
    }
  ]
}

并且您运行以下命令:

cmake -S /path/to/source --preset=ninja-release

这将使用 Ninja 生成器在 /path/to/source/build/ninja-release 中生成一个构建目录,并将 CMAKE_BUILD_TYPE 设置为 Release

如果您想查看可用预设的列表,可以运行:

cmake -S /path/to/source --list-presets

这将在不生成构建树的情况下,列出 /path/to/source/CMakePresets.json/path/to/source/CMakeUsersPresets.json 中可用的预设。

在 cmake-gui 中使用预设

如果项目通过 CMakePresets.jsonCMakeUserPresets.json 提供了预设,预设列表将在 cmake-gui(1) 的源目录和二进制目录之间的一个下拉菜单中显示。选择一个预设将设置二进制目录、生成器、环境变量和缓存变量,但所有这些选项都可以在选择预设后覆盖。

调用构建系统

在生成构建系统后,可以通过调用特定的构建工具来构建软件。对于 IDE 生成器,这可能涉及将生成的项目文件加载到 IDE 中以调用构建。

CMake 知道调用构建所需的特定构建工具,因此通常,在生成后从命令行构建构建系统或项目,可以在构建目录中调用以下命令:

$ cmake --build .

--build 标志启用 cmake(1) 工具的操作模式。它调用与 生成器 关联的 CMAKE_MAKE_PROGRAM 命令,或者用户配置的构建工具。

--build 模式还接受 --target 参数来指定要构建的特定目标,例如特定的库、可执行文件或自定义目标,或像 install 这样的特定特殊目标。

$ cmake --build . --target myexe

--build 模式还接受 --config 参数,以防使用多配置生成器指定要构建的特定配置。

$ cmake --build . --target myexe --config Release

--config 选项对于生成器为配置生成特定构建系统(在调用 cmake 时使用 CMAKE_BUILD_TYPE 变量选择)的情况无效。

某些构建系统会省略构建期间调用的命令行详细信息。可以使用 --verbose 标志来显示这些命令行。

$ cmake --build . --target myexe --verbose

--build 模式还可以通过在 -- 之后列出它们来将特定的命令行选项传递给底层构建工具。这对于向构建工具指定选项很有用,例如在作业失败后继续构建,而 CMake 没有提供高级用户界面。

对于所有生成器,都可以在调用 CMake 之后运行底层构建工具。例如,在生成 Unix Makefiles 生成器后可以执行 make 来调用构建,或者生成 Ninja 生成器后执行 ninja 等。 IDE 构建系统通常提供用于构建项目的命令行工具,也可以调用这些工具。

选择目标

CMake 文件中描述的每个可执行文件和库都是一个构建目标,构建系统可能描述自定义目标,无论是内部使用还是供用户消费,例如创建文档。

CMake 为所有提供 CMake 文件的构建系统提供了一些内置目标。

all

默认目标由 Makefile 生成器Ninja 生成器 使用。构建构建系统中的所有目标,除了那些被它们的 EXCLUDE_FROM_ALL 目标属性或 EXCLUDE_FROM_ALL 目录属性排除的。对于 XcodeVisual Studio 生成器,使用 ALL_BUILD 这个名称。

help

列出可供构建的目标。使用 Makefile 生成器Ninja 生成器 时可用此目标,具体输出取决于工具。

clean

删除已构建的对象文件和其他输出文件。 Makefile 生成器 为每个目录创建 clean 目标,以便可以清理单个目录。 Ninja 工具提供了自己的细粒度 -t clean 系统。

测试

运行测试。如果 CMake 文件提供基于 CTest 的测试,则此目标会自动可用。另请参阅 运行测试

安装

安装软件。如果软件使用 install() 命令定义了安装规则,则此目标会自动可用。另请参阅 软件安装

package

创建二进制包。如果 CMake 文件提供基于 CPack 的包,则此目标会自动可用。

package_source

创建源代码包。如果 CMake 文件提供基于 CPack 的包,则此目标会自动可用。

对于 Makefile 生成器,提供了二进制构建目标的 /fast 变体。 /fast 变体用于构建指定目标而不考虑其依赖项。依赖项不会被检查,也不会在过时时重新构建。 Ninja 生成器 在依赖项检查方面足够快,因此没有为该生成器提供此类目标。

Makefile 生成器 还提供了用于预处理、汇编和编译特定目录中单个文件的构建目标。

$ make foo.cpp.i
$ make foo.cpp.s
$ make foo.cpp.o

文件名扩展名已内置到目标名称中,因为可能存在具有相同名称但扩展名不同的文件。但是,也提供了没有文件扩展名的构建目标。

$ make foo.i
$ make foo.s
$ make foo.o

在包含 foo.cfoo.cpp 的构建系统中,构建 foo.i 目标将预处理这两个文件。

指定构建程序

--build 模式调用的程序由 CMAKE_MAKE_PROGRAM 变量决定。对于大多数生成器,不需要配置特定的程序。

生成器

默认 make 程序

备选

XCode

xcodebuild

Unix Makefiles

make

NMake Makefiles

nmake

jom

NMake Makefiles JOM

jom

nmake

MinGW Makefiles

mingw32-make

MSYS Makefiles

make

Ninja

ninja

Visual Studio

msbuild

Watcom WMake

wmake

jom 工具能够读取 NMake 风格的 makefiles 并并行构建,而 nmake 工具总是顺序构建。使用 NMake Makefiles 生成器生成后,用户可以运行 jom 而不是 nmake。当使用 NMake Makefiles 生成器并设置 CMAKE_MAKE_PROGRAMjom 时,--build 模式也会使用 jom。为了方便起见,提供了 NMake Makefiles JOM 生成器来正常查找 jom 并将其用作 CMAKE_MAKE_PROGRAM。为了完整起见,nmake 是一个替代工具,它可以处理 NMake Makefiles JOM 生成器的输出,但这样做会是一种性能下降。

软件安装

可以在 CMake 缓存中设置 CMAKE_INSTALL_PREFIX 变量来指定安装提供软件的位置。如果提供的软件具有安装规则(使用 install() 命令指定),则它们会将构件安装到该前缀下。在 Windows 上,默认安装位置对应于 ProgramFiles 系统目录,该目录可能特定于架构。在 Unix 主机上,/usr/local 是默认安装位置。

CMAKE_INSTALL_PREFIX 变量始终指向目标文件系统上的安装前缀。

在交叉编译或打包场景中,其中 sysroot 是只读的,或者 sysroot 应该保持不变,可以设置 CMAKE_STAGING_PREFIX 变量到一个实际安装文件的位置。

命令:

$ cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local \
  -DCMAKE_SYSROOT=$HOME/root \
  -DCMAKE_STAGING_PREFIX=/tmp/package
$ cmake --build .
$ cmake --build . --target install

将导致文件安装到宿主机器上的路径,例如 /tmp/package/lib/libfoo.so。宿主机器上的 /usr/local 位置不受影响。

某些提供的软件可能指定 uninstall 规则,但 CMake 本身默认不生成这些规则。

运行测试

CMake 分发版附带 ctest(1) 工具,用于执行提供的测试并报告结果。 test 构建目标可用于运行所有可用测试,但 ctest(1) 工具允许对运行哪些测试、如何运行以及如何报告结果进行精细控制。在构建目录中执行 ctest(1) 等同于运行 test 目标。

$ ctest

可以传递正则表达式来仅运行名称与表达式匹配的测试。要仅运行名称中带有 Qt 的测试:

$ ctest -R Qt

也可以通过正则表达式排除测试。要仅运行名称中不带 Qt 的测试:

$ ctest -E Qt

可以通过将 -j 参数传递给 ctest(1) 来并行运行测试。

$ ctest -R Qt -j8

也可以设置环境变量 CTEST_PARALLEL_LEVEL 以避免传递 -j 的需要。

默认情况下,ctest(1) 不会打印测试的输出。命令行参数 -V(或 --verbose)启用详细模式以打印所有测试的输出。 --output-on-failure 选项仅打印失败测试的输出。环境变量 CTEST_OUTPUT_ON_FAILURE 可以设置为 1,作为传递 --output-on-failure 选项给 ctest(1) 的替代方法。