用户交互指南

简介

当一个软件包在软件源代码中提供基于 CMake 的构建系统时,软件使用者需要运行 CMake 用户交互工具才能构建它。

运行良好的基于 CMake 的构建系统不会在源代码目录中创建任何输出,因此通常,用户执行非源代码构建并在其中执行构建。首先,必须指示 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 工具可能会发出警告,针对的是软件提供者,而不是软件使用者。此类警告以“此警告针对项目开发人员”结尾。用户可以通过向 cmake(1) 传递 -Wno-dev 标志来禁用此类警告。

cmake-gui 工具

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

必须先填充源目录和二进制目录。始终建议对源目录和构建目录使用不同的目录。

Choosing source and binary directories

生成构建系统

有几个用户界面工具可以用来从 CMake 文件生成构建系统。 ccmake(1)cmake-gui(1) 工具指导用户设置各种必要的选项。可以调用 cmake(1) 工具在命令行上指定选项。本手册介绍了可以使用任何用户界面工具设置的选项,尽管在每个工具中设置选项的方式不同。

命令行环境

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

在 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 的输出包含 generators 的列表,供用户选择。请注意,生成器名称区分大小写。

在类 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 生成项目文件。

一些 IDE 如 KDevelop4、QtCreator 和 CLion 原生支持基于 CMake 的构建系统。这些 IDE 提供用户界面,用于选择要使用的基础生成器,通常在Makefile或基于Ninja的生成器之间选择。

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

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

可以使用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,用作确定调试/优化标志的依据。这仅与单配置构建系统(如 MakefileNinja)相关。适用于 Visual Studio 和 Xcode 的多配置构建系统会忽略此设置。

CMAKE_INSTALL_PREFIX

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

CMAKE_TOOLCHAIN_FILE

包含交叉编译数据(如 toolchain sysroot)的文件。

BUILD_SHARED_LIBS

对于不带类型的 add_library() 命令,指示是要构建共享库还是静态库

CMAKE_EXPORT_COMPILE_COMMANDS

为基于 clang 的工具生成 compile_commands.json 文件

CMAKE_EXPORT_BUILD_DATABASE

为基于 clang 的工具生成 build_database.json 文件

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

CMake 未提供不同提供的构建系统之间这些变量的命名约定,只不过前缀为 CMAKE_ 的变量通常是指 CMake 本身提供的选项,不应在第三方选项中使用,后者应使用自己的前缀。工具 cmake-gui(1) 可以按其前缀定义的组显示选项,因此第三方确保他们使用自洽的前缀是有意义的。

在命令行中设置变量

无论是在创建初始构建

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

时还是随后调用 cmake(1) 时,都可以在命令行中设置 CMake 变量

$ cd build
$ cmake . -DCMAKE_BUILD_TYPE=Debug

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

$ cd build
$ cmake . -UMyPackage_DIR

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

工具 cmake(1) 允许使用 -C 选项指定用于使用初始缓存的文件。这对于简化重复需要相同缓存项的命令和脚本非常有用。

使用 cmake-gui 设置变量

可以使用“添加条目”按钮在 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

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

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

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

这将列出 /path/to/source/CMakePresets.json/path/to/source/CMakeUsersPresets.json 中可用的预设,而无需生成构建树。

在 cmake-gui 中使用预设

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

调用构建系统

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

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

$ cmake --build .

--build 标志为 cmake(1) 工具启用特定操作模式。它调用与 generator 关联的 CMAKE_MAKE_PROGRAM 命令,或由用户配置的构建工具。

--build 模式还接受参数 --target,以指定一个特定的构建目标,例如特定的库、可执行文件或自定义目标,或特定特殊目标,如 install

$ cmake --build . --target myexe

--build 模式在多配置生成器时也会接受 --config 参数,以指定要构建的特定配置

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

--config 选项在生成器生成特定于配置的构建系统时无效,该配置是在使用 CMAKE_BUILD_TYPE 变量调用 CMake 时选择的。

某些构建系统省略了在构建过程中调用的命令行的详细信息。可以使用 --verbose 标志显示这些命令行

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

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

对于所有生成器,在调用 CMake 后运行底层构建工具是可行的。例如,在使用 Unix Makefiles 生成器生成后,可以执行 make 以调用构建,或者在使用 Ninja 生成器生成后,执行 ninja,依此类推。IDE 构建系统通常会提供可调用的构建项目命令行工具。

选择目标

CMake 文件中描述的每个可执行文件和库都是构建目标,而构建系统可以描述自定义目标,用于供内部使用或用户使用,例如创建文档。

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

全部

MakefileNinja 生成器使用的默认目标。除了被其目标属性 EXCLUDE_FROM_ALL 或目录属性 EXCLUDE_FROM_ALL 排除的目标外,构建构建系统中的所有目标。对于 Xcode 和 Visual Studio 生成器,此目的使用名称 ALL_BUILD

帮助

列出可构建的目标。使用 Unix MakefilesNinja 生成器时会生成该目标,具体输出取决于工具。

清理

删除已构建的对象文件和其他输出文件。基于 Makefile 的生成器每目录创建一个 clean 目标,以便清理单个目录。Ninja 工具自带细化的 -t clean 系统。

测试

运行测试。仅当 CMake 文件提供基于 CTest 的测试时,此目标才会自动生成。另请参阅 运行测试

安装

安装软件。仅当软件使用 install() 命令定义安装规则时,才自动生成此目标。另请参阅 软件安装

打包

创建一个二进制包。仅当 CMake 文件提供基于 CPack 的包时,才自动生成此目标。

打包源文件

创建一个源文件包。仅当 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 格式的 Makefile,并并行构建,而 nmake 一直串行构建。生成 NMake Makefiles 后,用户可以使用 jom 代替 nmake。如果在使用 NMake Makefiles 生成器时将 CMAKE_MAKE_PROGRAM 设置为 jom,那么 --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,作为向 ctest(1) 传递 --output-on-failure 选项的替代方法。