ExternalProject

此模块提供了命令,用于在 CMake 构建阶段下载和构建外部项目。

在 CMake 项目中加载此模块,使用

include(ExternalProject)

外部项目定义

ExternalProject_Add

ExternalProject_Add() 函数创建一个自定义目标,用于驱动外部项目的下载、更新/修补、配置、构建、安装和测试步骤。

ExternalProject_Add(<name> [<option>...])

如果需要,过程中的各个步骤可以独立驱动(例如,用于 CDash 提交),并且可以定义额外的自定义步骤,同时能够控制步骤依赖关系。用于管理外部项目的目录结构也可以进行自定义。该函数支持大量选项,可用于定制外部项目的行为。

目录选项

大多数情况下,默认的目录布局就足够了。主项目通常不需要更改,这在很大程度上是一个实现细节。但在某些情况下,控制目录布局可能有用或必要。目录选项可能更有用的地方在于,主构建可以使用 ExternalProject_Get_Property() 命令检索其值,从而允许主项目引用外部项目的构建产物。

PREFIX <dir>

外部项目的根目录。除非下面另有说明,否则与外部项目相关的所有其他目录都将在此目录下创建。

TMP_DIR <dir>

用于存储临时文件的目录。

STAMP_DIR <dir>

用于存储每个步骤时间戳的目录。各个步骤的日志文件也在此处创建,除非被 LOG_DIR 覆盖(参见下面的 *日志选项*)。

LOG_DIR <dir>

3.14 版新增。

用于存储每个步骤日志的目录。

DOWNLOAD_DIR <dir>

在解压之前存储下载文件的目录。此目录仅由 URL 下载方法使用,所有其他下载方法直接使用 `SOURCE_DIR`。

SOURCE_DIR <dir>

下载内容将被解压的源目录,或者对于非 URL 下载方法,是应检出、克隆等存储库的目录。如果未指定下载方法,则此目录必须指向一个已解压或已克隆/检出的现有目录。

注意

如果指定了下载方法,则源目录中现有的任何内容都可能被删除。只有 URL 下载方法在开始下载前会检查此目录是缺失还是为空,如果非空则会报错。所有其他下载方法都会默默丢弃源目录中之前的内容。

BINARY_DIR <dir>

指定构建目录的位置。如果启用了 `BUILD_IN_SOURCE`,则忽略此选项。

INSTALL_DIR <dir>

安装前缀,将放置在 `` 占位符中。这实际上并不会将外部项目配置为安装到给定的前缀。这必须通过将适当的参数传递给外部项目配置步骤来完成,例如使用 ``。

如果上面任何 `..._DIR` 选项未指定,则它们的默认值计算如下。如果指定了 `PREFIX` 选项或设置了 `EP_PREFIX` 目录属性,则外部项目将在指定前缀下构建和安装。

TMP_DIR      = <prefix>/tmp
STAMP_DIR    = <prefix>/src/<name>-stamp
DOWNLOAD_DIR = <prefix>/src
SOURCE_DIR   = <prefix>/src/<name>
BINARY_DIR   = <prefix>/src/<name>-build
INSTALL_DIR  = <prefix>
LOG_DIR      = <STAMP_DIR>

否则,如果设置了 `EP_BASE` 目录属性,则外部项目的组件将存储在指定的基目录下。

TMP_DIR      = <base>/tmp/<name>
STAMP_DIR    = <base>/Stamp/<name>
DOWNLOAD_DIR = <base>/Download/<name>
SOURCE_DIR   = <base>/Source/<name>
BINARY_DIR   = <base>/Build/<name>
INSTALL_DIR  = <base>/Install/<name>
LOG_DIR      = <STAMP_DIR>

如果未指定 `PREFIX`、`EP_PREFIX` 或 `EP_BASE`,则默认是将 `PREFIX` 设置为 `-prefix`。相对路径的解释是相对于调用 `ExternalProject_Add()` 时 `CMAKE_CURRENT_BINARY_DIR` 的点。

下载步骤选项

如果 `SOURCE_DIR` 选项用于指向一个现有的非空目录,则可以省略下载方法。否则,必须指定以下下载方法之一(不应给出多个下载方法),或提供自定义的 `DOWNLOAD_COMMAND`。

DOWNLOAD_COMMAND <cmd>...

覆盖下载步骤所使用的命令(支持 生成器表达式)。如果指定了此选项,所有其他下载选项都将被忽略。为 `` 提供空字符串实际上会禁用下载步骤。

URL

URL <url1> [<url2>...]

外部项目源的路径和/或 URL 列表。当给出多个 URL 时,它们将依次尝试,直到成功一个。URL 可以是本地文件系统中的普通路径(在这种情况下,它必须是提供的唯一 URL)或 file(DOWNLOAD) 命令支持的任何可下载 URL。本地文件系统路径可以指向现有目录或存档文件,而 URL 预期指向可以被视为存档的文件。当使用存档时,它将自动解压,除非设置了 `DOWNLOAD_NO_EXTRACT` 选项来阻止它。存档类型是通过检查实际内容而不是基于文件扩展名的逻辑来确定的。

Version 3.7 changed: 允许多个 URL。

URL_HASH <algo>=<hashValue>

要下载的存档文件的哈希值。参数应为 `=` 的形式,其中 `algo` 可以是 `` 命令支持的任何哈希算法。强烈建议为 URL 下载指定此选项,因为它能确保下载内容的完整性。它也用于检查之前下载的文件,如果本地目录已有与指定哈希匹配的文件,则可以完全避免连接到远程位置。

URL_MD5 <md5>

等同于 `URL_HASH MD5=`。

DOWNLOAD_NAME <fname>

用于下载文件的文件名。如果未给定,则使用 URL 的末尾来确定文件名。此选项很少需要,默认名称通常合适,并且通常不用于 `ExternalProject` 模块内部代码之外。

DOWNLOAD_EXTRACT_TIMESTAMP <bool>

在 3.24 版本中添加。

当指定为真值时,解压文件的修改时间将与存档中的时间匹配。当为假时,解压文件的修改时间将反映执行解压的时间。如果下载 URL 发生更改,基于存档中修改时间的解压可能导致依赖目标未在应重建时重建。因此,除非文件修改时间在项目中有任何意义,否则请为此选项使用假值。如果未给出 `DOWNLOAD_EXTRACT_TIMESTAMP`,则默认值为假。参见策略 CMP0135

DOWNLOAD_NO_EXTRACT <bool>

3.6 版本新增。

通过为此选项传递布尔真值,允许禁用下载步骤的解压部分。如果未给出此选项,则在需要时会自动解压下载的内容。如果禁用了解压,则在后续步骤中,下载文件的完整路径可作为 `` 使用,或者作为属性 `DOWNLOADED_FILE`,通过 `` 命令获取。

DOWNLOAD_NO_PROGRESS <bool>

可用于禁用下载进度日志记录。如果未给出此选项,将记录下载进度消息。

TIMEOUT <seconds>

文件下载操作允许的最大时间。

INACTIVITY_TIMEOUT <seconds>

3.19 版本新增。

在一段时间不活动后终止操作。

HTTP_USERNAME <username>

3.7 版本中新增。

下载操作需要的用户名(如果需要身份验证)。

HTTP_PASSWORD <password>

3.7 版本中新增。

下载操作需要的密码(如果需要身份验证)。

HTTP_HEADER <header1> [<header2>...]

3.7 版本中新增。

为下载操作提供任意的 HTTP 头部列表。这对于访问 AWS 等系统中的内容非常有用。

TLS_VERSION <min>

3.30 版本新增。

为 `https://` URL 指定最低 TLS 版本。如果未提供此选项,则将使用 `CMAKE_TLS_VERSION` 变量或 `CMAKE_TLS_VERSION` 环境变量的值(参见 file(DOWNLOAD))。

此选项也适用于 `git clone` 调用,尽管默认行为不同。如果未指定 `TLS_VERSION` 选项、`CMAKE_TLS_VERSION` 变量或 `CMAKE_TLS_VERSION` 环境变量,则行为将由 git 的默认设置或用户可能全局设置的 `http.sslVersion` git 配置选项决定。

TLS_VERIFY <bool>

指定是否应对 `https://` URL 执行证书验证。如果未提供此选项,则将使用 `CMAKE_TLS_VERIFY` 变量或 `CMAKE_TLS_VERIFY` 环境变量的值(参见 file(DOWNLOAD))。如果两者均未设置,则不会执行证书验证。在无法提供 `URL_HASH` 的情况下,此选项可以作为替代验证措施。

此选项也适用于 `git clone` 调用,尽管默认行为不同。如果未指定 `TLS_VERIFY` 选项、`CMAKE_TLS_VERIFY` 变量或 `CMAKE_TLS_VERIFY` 环境变量,则行为将由 git 的默认设置(true)或用户可能全局设置的 `http.sslVerify` git 配置选项决定。

Version 3.6 changed: 以前此选项不适用于 `git clone` 调用。

Version 3.30 changed: 以前未检查 `CMAKE_TLS_VERIFY` 环境变量。

TLS_CAINFO <file>

如果启用了 `TLS_VERIFY`,则指定一个用于自定义证书颁发机构文件的文件。如果未指定此选项,则将使用 `CMAKE_TLS_CAINFO` 变量的值(参见 file(DOWNLOAD))。

NETRC <level>

3.11 版本新增。

指定是否使用 `.netrc` 文件进行操作。如果未指定此选项,则将使用 `CMAKE_NETRC` 变量的值(参见 file(DOWNLOAD))。有效级别包括:

IGNORED

忽略 `.netrc` 文件。这是默认值。

OPTIONAL

`.netrc` 文件是可选的,并且优先使用 URL 中的信息。文件将被扫描以查找 URL 中未指定的信息。

REQUIRED

`.netrc` 文件是必需的,并且会忽略 URL 中的信息。

NETRC_FILE <file>

3.11 版本新增。

如果 `NETRC` 级别为 `OPTIONAL` 或 `REQUIRED`,则指定一个替代的 `.netrc` 文件,而不是您主目录中的那个。如果未指定此选项,则将使用 `CMAKE_NETRC_FILE` 变量的值(参见 file(DOWNLOAD))。

Version 3.1 added: 增加了对 `tbz2`、`.tar.xz`、`.txz` 和 `.7z` 扩展名的支持。

Version 4.1 added: 支持 `cmake -E tar` 可以提取的所有存档类型,无论文件扩展名如何。

Git

注意:如果使用此下载方法,则需要 Git 版本 1.6.5 或更高版本。

GIT_REPOSITORY <url>

Git 存储库的 URL。可以使用 `` 命令理解的任何 URL。

Version 3.27 changed: 相对 URL 将根据父项目的远程进行解析,受 CMP0150 约束。请参阅策略文档,了解远程如何选择,包括远程选择失败的情况。本地文件系统远程应始终使用绝对路径。

GIT_TAG <tag>

Git 分支名称、标签或提交哈希。请注意,分支名称和标签通常应指定为远程名称(即 `origin/myBranch` 而不是 `myBranch`)。这确保了如果远程端移动了其标签、重基了分支或重写了历史记录,本地克隆仍能正确更新。但总的来说,出于多种原因,优先使用特定的提交哈希:

  • 如果本地克隆已经拥有与哈希对应的提交,那么每次重新运行 CMake 时都不需要执行 `git fetch` 来检查更改。如果使用许多外部项目,这可以显著加速。

  • 使用特定的 git 哈希可确保主项目自己的历史记录可以追溯到外部项目演进的特定点。如果改用分支或标签名称,那么检出主项目的特定提交并不一定会将整个构建固定在外部项目生命周期的特定点。缺乏这种确定性行为会使主项目失去可追溯性和可重复性。

如果启用了 `GIT_SHALLOW`,则 `GIT_TAG` 仅适用于分支名称和标签。不允许使用提交哈希。

请注意,如果未提供,`GIT_TAG` 默认为 `master`,而不是默认的 Git 分支名称。

GIT_REMOTE_NAME <name>

远程的可选名称。如果未指定此选项,则默认为 `origin`。

GIT_SUBMODULES <module>...

应更新的特定 git 子模块。如果未提供此选项,则将更新所有 git 子模块。

Version 3.16 changed: 当 `CMP0097` 设置为 `NEW` 时,如果此值设置为空字符串,则不初始化或更新任何子模块。

GIT_SUBMODULES_RECURSE <bool>

在 3.17 版本中添加。

通过将 `--recursive` 标志传递给 `git submodule update`,指定是否应递归更新 git 子模块(如果有)。如果未指定,则默认为开启。

GIT_SHALLOW <bool>

3.6 版本新增。

启用此选项时,`git clone` 操作将收到 `--depth 1` 选项。这将执行浅克隆,避免下载整个历史记录,而是仅检索由 `GIT_TAG` 选项指定的提交。

GIT_PROGRESS <bool>

版本 3.8 新增。

启用此选项时,它指示 `git clone` 操作通过传递 `--progress` 选项来报告其进度。没有此选项,大型项目的克隆步骤可能会显得构建停滞,因为直到克隆操作完成之前,不会记录任何内容。虽然此选项可用于提供进度以防止构建停滞的出现,但如果使用大量外部项目,它也可能导致构建过于冗长。

GIT_CONFIG <option1> [<option2>...]

版本 3.8 新增。

指定要传递给 `git clone` 的配置选项列表。列出的每个选项都将转换为 `git clone` 命令行上的一个 `--config

GIT_REMOTE_UPDATE_STRATEGY <strategy>

在 3.18 版本中新增。

当 `GIT_TAG` 指向远程分支时,可以使用此选项来指定更新步骤的行为。`` 必须是以下之一:

CHECKOUT

忽略本地分支,并始终检出 `GIT_TAG` 指定的分支。

REBASE

尝试将当前分支重基到 `GIT_TAG` 指定的分支。如果有未提交的本地更改,它们将首先被暂存,并在重基后再次弹出。如果重基或弹出暂存更改失败,将中止重基并停止错误。当未提供 `GIT_REMOTE_UPDATE_STRATEGY` 时,这是默认策略,除非默认值已被 `CMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY` 覆盖(见下文)。请注意,如果 `GIT_TAG` 中指定的分支与当前正在跟踪的上游分支不同,则进行重基不安全。在这种情况下,`REBASE` 将被静默地视为 `CHECKOUT`。

REBASE_CHECKOUT

与 `REBASE` 相同,不同之处在于,如果重基失败,将在重基之前的原始 `HEAD` 位置创建一个带注释的标签,然后像 `CHECKOUT` 策略一样检出 `GIT_TAG`。带注释的标签上存储的消息将提供有关尝试了什么的信息,并且标签名称将包含一个时间戳,以便每次失败的运行都会添加一个新标签。此策略可确保不会丢失任何更改,但如果 `GIT_TAG` 指向一个有效的 ref,则更新应始终成功,除非存在无法成功弹出的未提交更改。

变量 `CMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY` 可以被设置以覆盖默认策略。此变量不应由项目设置,而是供用户设置。它主要用于持续集成脚本,以确保当远程分支上的历史记录被重写时,构建不会因重基操作中的冲突而导致意外的更改或构建失败。

Subversion

SVN_REPOSITORY <url>

Subversion 存储库的 URL。

SVN_REVISION -r<rev>

从 Subversion 存储库检出的修订版本。

SVN_USERNAME <username>

Subversion 检出和更新的用户名。

SVN_PASSWORD <password>

Subversion 检出和更新的密码。

SVN_TRUST_CERT <bool>

指定是否信任 Subversion 服务器站点证书。如果启用,则 `--trust-server-cert` 选项将传递给 `svn` 检出和更新命令。

Mercurial

HG_REPOSITORY <url>

Mercurial 存储库的 URL。

HG_TAG <tag>

Mercurial 分支名称、标签或提交 ID。

CVS

CVS_REPOSITORY <cvsroot>

CVS 存储库的 CVSROOT。

CVS_MODULE <mod>

要从 CVS 存储库检出的模块。

CVS_TAG <tag>

要从 CVS 存储库检出的标签。

更新步骤选项

每当 CMake 重新运行时,默认情况下,外部项目的源文件都会被更新,前提是下载方法支持更新(例如,如果 `GIT_TAG` 不指向特定提交,则会检查 git 存储库)。

UPDATE_COMMAND <cmd>...

使用自定义命令覆盖下载方法的更新步骤。命令可以使用 生成器表达式

UPDATE_DISCONNECTED <bool>

版本 3.2 中新增。

启用此选项时,将跳过更新步骤(但请参阅下面已更改的行为,其中情况并非如此)。它不会阻止下载步骤。更新步骤仍可作为步骤目标(参见下面的 ExternalProject_Add_StepTargets())添加并手动调用。如果您希望允许开发人员在断开网络连接时构建项目(网络仍可能需要用于下载步骤),则此选项很有用。

Version 3.27 changed: 当 `UPDATE_DISCONNECTED` 为 true 时,如果更新或下载步骤的任何详细信息发生更改,将执行更新步骤。此外,如果使用 git 下载/更新方法,更新逻辑将修改为跳过与远程的通信尝试。如果 `GIT_TAG` 引用一个本地未知的 ref,更新步骤将以致命错误停止。

当此选项存在时,通常建议将其作为开发人员控制下的缓存变量,而不是硬编码。如果未提供此选项,则默认值将从 `EP_UPDATE_DISCONNECTED` 目录属性中获取。如果该属性也未定义,则按正常方式执行更新。`EP_UPDATE_DISCONNECTED` 目录属性旨在方便控制项目目录层次结构整个部分的 `UPDATE_DISCONNECTED` 行为,并且可能是为开发人员提供控制是否执行更新的更方便的方法(假设项目还提供了缓存变量或其他方便的方法来设置目录属性)。

这可能会导致自动为 `download` 步骤创建步骤目标。参见策略 CMP0114

修补步骤选项

PATCH_COMMAND <cmd>...

指定一个自定义命令,用于在更新后修补源代码。默认情况下,未定义修补命令。请注意,定义一个能够稳健执行的适当的修补命令可能会相当困难,特别是对于 git 这样的下载方法,其中更改 `GIT_TAG` 不会丢弃先前修补程序所做的更改,但修补命令将在更新到新标签后再次调用。

配置步骤选项

配置步骤在下载和更新步骤之后运行。默认情况下,假定外部项目是一个 CMake 项目,但这可以在需要时被覆盖。

CONFIGURE_COMMAND <cmd>...

默认的配置命令使用一些基于主项目的选项运行 CMake。添加的选项通常只是那些用于使用与主项目相同的生成器的选项,但可以给出 `CMAKE_GENERATOR` 选项来覆盖它。项目负责添加任何它希望从主项目重用或另外指定的工具链详细信息、标志或其他设置(参见下面的 `CMAKE_ARGS`、`CMAKE_CACHE_ARGS` 和 `CMAKE_CACHE_DEFAULT_ARGS`)。

对于非 CMake 外部项目,必须使用 `CONFIGURE_COMMAND` 选项来覆盖默认的配置命令(支持 生成器表达式)。对于不需要配置步骤的项目,请将此选项指定为空字符串作为要执行的命令。

CMAKE_COMMAND /.../cmake

为配置步骤指定一个替代的 cmake 可执行文件(使用绝对路径)。这通常不推荐,因为在整个构建中使用相同的 CMake 版本通常是可取的。如果使用了 `CONFIGURE_COMMAND` 指定了自定义配置命令,则将忽略此选项。

CMAKE_GENERATOR <gen>

覆盖配置步骤使用的 CMake 生成器。如果没有此选项,将使用与主构建相同的生成器。如果使用了 `CONFIGURE_COMMAND` 选项指定了自定义配置命令,则将忽略此选项。

CMAKE_GENERATOR_PLATFORM <platform>

版本 3.1 中新增。

将生成器特定的平台名称传递给 CMake 命令(参见 CMAKE_GENERATOR_PLATFORM)。提供此选项而未提供 `CMAKE_GENERATOR` 选项是错误的。

CMAKE_GENERATOR_TOOLSET <toolset>

将生成器特定的工具集名称传递给 CMake 命令(参见 CMAKE_GENERATOR_TOOLSET)。提供此选项而未提供 `CMAKE_GENERATOR` 选项是错误的。

CMAKE_GENERATOR_INSTANCE <instance>

3.11 版本新增。

将生成器特定的实例选择传递给 CMake 命令(参见 CMAKE_GENERATOR_INSTANCE)。提供此选项而未提供 `CMAKE_GENERATOR` 选项是错误的。

CMAKE_ARGS <arg>...

指定的参数将传递给 `cmake` 命令。它们可以是 `cmake` 命令理解的任何参数,不仅仅是 `-D...` 参数定义的缓存值(另请参见 CMake Options)。

Version 3.3 added: 参数可以支持 生成器表达式

CMAKE_CACHE_ARGS <arg>...

这是指定缓存变量的另一种方式,当命令行的长度可能成为问题时。参数预计为 `-Dvar:STRING=value` 的形式,然后转换为 CMake set() 命令,并使用 `FORCE` 选项。这些 `set()` 命令被写入一个预加载脚本,然后使用 `cmake -C` 命令行选项进行应用。

Version 3.3 added: 参数可以支持 生成器表达式

CMAKE_CACHE_DEFAULT_ARGS <arg>...

版本 3.2 中新增。

这与 `CMAKE_CACHE_ARGS` 选项相同,只是 `set()` 命令不包含 `FORCE` 关键字。这意味着这些值仅充当初始默认值,并且不会覆盖先前运行中已设置的任何变量。请谨慎使用此选项,因为它可能导致不同的行为,具体取决于构建是首次启动还是重用先前的构建内容。

Version 3.15 added: 如果 CMake 生成器是 `Green Hills MULTI` 且未被覆盖,则原始项目的 GHS 工具集和目标系统自定义缓存变量的设置将被传播到外部项目中。

SOURCE_SUBDIR <dir>

3.7 版本中新增。

如果未指定 `CONFIGURE_COMMAND` 选项,则配置步骤假定外部项目在其源树的顶部(即在 `SOURCE_DIR` 中)有一个 `CMakeLists.txt` 文件。`SOURCE_SUBDIR` 选项可用于指向源树内的另一个目录,将其用作 CMake 源树的顶部。这必须是相对路径,并且将相对于 `SOURCE_DIR` 进行解释。

Version 3.14 added: 当 `BUILD_IN_SOURCE` 选项启用时,`BUILD_COMMAND` 用于指向源树内的另一个目录。

CONFIGURE_HANDLED_BY_BUILD <bool>

在 3.20 版本中添加。

启用此选项会将配置步骤对其他外部项目的依赖关系放宽为仅顺序依赖。这意味着配置步骤将在其外部项目依赖项构建后执行,但当其某个外部项目依赖项重建时,它不会被标记为脏。当构建步骤足够智能以确定是否需要重新运行配置步骤时,可以启用此选项。CMake 和 Meson 是构建系统中的例子,其构建步骤足够智能,可以知道配置步骤是否需要重新运行。

CONFIGURE_ENVIRONMENT_MODIFICATION <modification>...

版本 4.2 中添加。

指定应为配置步骤修改的环境变量。

设置一个(分号分隔的列表)环境变量和值,形式为 ``,其中 `` 是要修改的环境变量的区分大小写的名称。条目按属性值中指定的顺序考虑。`OP` 可以是以下之一:

  • reset:重置为未修改的值,忽略此条目之前对 `MYVAR` 的所有修改。请注意,这将把变量重置为 ENVIRONMENT 设置的值(如果已设置),否则重置为 CTest 执行其余部分的状态。

  • set:用 `VALUE` 替换 `MYVAR` 的当前值。

  • unset:取消设置 `MYVAR` 的当前值。

  • string_append:使用主机平台的路径列表分隔符(Windows 上为 `;`,其他地方为 `:`),将单个 `VALUE` 追加到 `MYVAR` 的当前值。

  • string_prepend:使用主机平台的路径列表分隔符(Windows 上为 `;`,其他地方为 `:`),将单个 `VALUE` 前置到 `MYVAR` 的当前值。

  • path_list_append:使用主机平台的路径列表分隔符(Windows 上为 `;`,其他地方为 `:`),将单个 `VALUE` 追加到 `MYVAR` 的当前值。

  • path_list_prepend:使用主机平台的路径列表分隔符(Windows 上为 `;`,其他地方为 `:`),将单个 `VALUE` 前置到 `MYVAR` 的当前值。

  • cmake_list_append:使用 `;` 作为分隔符,将单个 `VALUE` 追加到 `MYVAR` 的当前值。

  • cmake_list_prepend:使用 `;` 作为分隔符,将单个 `VALUE` 前置到 `MYVAR` 的当前值。

ExternalProject_Add(example
  ... # Download options, etc...
  CONFIGURE_ENVIRONMENT_MODIFICATION
    SDKROOT=set:macosx
    PKG_CONFIG_PATH=set:$ENV{PKG_CONFIG_PATH}
)

此代码段在配置示例项目时定义了两个环境变量。`SDKROOT` 环境变量被设置为 `macosx`,而 `PKG_CONFIG_PATH` 的值将被转发给外部项目。

环境变量修改与 `LIST_SEPARATOR` 一起使用,将分隔符替换为环境变量中的 `;`。

ExternalProject_Add(example
  ... # Download options, etc...
  LIST_SEPARATOR ,
  CONFIGURE_ENVIRONMENT_MODIFICATION
    LIST_VAR=set:a,b,c
)

此代码段和环境变量 `LIST_VAR` 将以值 `a;b;c` 传递给配置命令调用。

构建步骤选项

如果配置步骤假定外部项目使用 CMake 作为其构建系统,则构建步骤也会如此。否则,构建步骤将假定是基于 Makefile 的构建,并将简单地运行 `make` 而不带任何参数作为默认构建步骤。如果需要,这可以用自定义构建命令来覆盖。

如果主项目和外部项目都使用 make 作为其构建工具,则外部项目的构建步骤将作为递归 make 使用 `$(MAKE)` 调用。这将从主项目向外部项目传递一些构建工具设置。如果主项目或外部项目未使用 make,除了配置步骤建立的设置外,将不会向外部项目传递任何构建工具设置(即,在主项目中运行 `ninja -v` 不会将 `-v` 传递给外部项目的构建步骤,即使它也使用 `ninja` 作为其构建工具)。

BUILD_COMMAND <cmd>...

覆盖默认构建命令(支持 生成器表达式)。如果未给出此选项,则将选择默认构建命令,以最合适的方式与主构建集成(例如,对于 Makefile 生成器使用递归 `make`,或者如果项目使用 CMake 构建则使用 ``)。可以将此选项指定为空字符串作为命令,使构建步骤无所作为。

BUILD_IN_SOURCE <bool>

启用此选项时,构建将在外部项目的源树内直接进行。这通常应避免,通常首选使用单独的构建目录,但当外部项目假定为内源构建时,这可能有用。如果不使用内源构建,则不应指定 `BINARY_DIR` 选项。

BUILD_ALWAYS <bool>

启用此选项会强制始终运行构建步骤。这可能是确保外部项目自身构建依赖项被评估而不是依赖于默认的基于时间戳的成功方法的最简单方法。除非开发人员预计会修改外部项目构建所依赖的某些内容,而这些内容无法通过步骤目标依赖项检测到(例如,使用 `SOURCE_DIR` 而没有下载方法,并且开发人员可能会修改 `SOURCE_DIR` 中的源文件),否则通常不需要此选项。

BUILD_BYPRODUCTS <file>...

版本 3.2 中新增。

指定由构建命令生成但可能由后续构建更新修改时间的文件。当使用 Ninja 生成器时,这可能也需要显式声明依赖项。这些最终将作为 `BYPRODUCTS` 传递给构建步骤自身对 `` 的底层调用,该调用有额外的文档。

BUILD_JOB_SERVER_AWARE <bool>

版本 3.28 新增。

指定构建步骤能够识别 GNU Make 作业服务器。有关详细信息,请参阅 `` 文档中的 `JOB_SERVER_AWARE` 选项。此选项仅在指定了显式的 `BUILD_COMMAND` 时才相关。

BUILD_ENVIRONMENT_MODIFICATION <modification>...

版本 4.2 中添加。

指定应为构建步骤修改的环境变量。

设置一个(分号分隔的列表)环境变量和值,形式为 ``,其中 `` 是要修改的环境变量的区分大小写的名称。条目按属性值中指定的顺序考虑。`OP` 可以是以下之一:

  • reset:重置为未修改的值,忽略此条目之前对 `MYVAR` 的所有修改。请注意,这将把变量重置为 ENVIRONMENT 设置的值(如果已设置),否则重置为 CTest 执行其余部分的状态。

  • set:用 `VALUE` 替换 `MYVAR` 的当前值。

  • unset:取消设置 `MYVAR` 的当前值。

  • string_append:使用主机平台的路径列表分隔符(Windows 上为 `;`,其他地方为 `:`),将单个 `VALUE` 追加到 `MYVAR` 的当前值。

  • string_prepend:使用主机平台的路径列表分隔符(Windows 上为 `;`,其他地方为 `:`),将单个 `VALUE` 前置到 `MYVAR` 的当前值。

  • path_list_append:使用主机平台的路径列表分隔符(Windows 上为 `;`,其他地方为 `:`),将单个 `VALUE` 追加到 `MYVAR` 的当前值。

  • path_list_prepend:使用主机平台的路径列表分隔符(Windows 上为 `;`,其他地方为 `:`),将单个 `VALUE` 前置到 `MYVAR` 的当前值。

  • cmake_list_append:使用 `;` 作为分隔符,将单个 `VALUE` 追加到 `MYVAR` 的当前值。

  • cmake_list_prepend:使用 `;` 作为分隔符,将单个 `VALUE` 前置到 `MYVAR` 的当前值。

安装步骤选项

如果配置步骤假定外部项目使用 CMake 作为其构建系统,则安装步骤也会如此。否则,安装步骤将假定是基于 Makefile 的构建,并将简单地运行 `make install` 作为默认构建步骤。如果需要,这可以用自定义安装命令来覆盖。

INSTALL_COMMAND <cmd>...

外部项目自身的安装步骤作为主项目的 *构建* 的一部分被调用。它在外部项目的构建步骤之后,并且可能在外部项目的测试步骤之前或之后(参见下面的 `TEST_BEFORE_INSTALL` 选项)。外部项目的安装规则不是主项目安装规则的一部分,因此,如果外部项目的任何内容应作为主构建的一部分进行安装,则需要在主构建中将其指定为附加的 `` 命令。默认安装步骤构建外部项目的 `install` 目标,但这可以用自定义命令使用此选项来覆盖(支持 生成器表达式)。将空字符串作为 `` 传递会使安装步骤无所作为。

INSTALL_BYPRODUCTS <file>...

3.26 版新增。

指定由安装命令生成但可能由后续安装更新修改时间的文件。当使用 Ninja 生成器时,这可能也需要显式声明依赖项。这些最终将作为 `BYPRODUCTS` 传递给安装步骤自身对 `` 的底层调用,该调用有额外的文档。

INSTALL_JOB_SERVER_AWARE <bool>

4.0 版本新增。

指定安装步骤能够识别 GNU Make 作业服务器。有关详细信息,请参阅 `` 文档中的 `JOB_SERVER_AWARE` 选项。此选项仅在指定了显式的 `INSTALL_COMMAND` 时才相关。

注意

如果在构建主项目时设置了 `CMAKE_INSTALL_MODE` 环境变量,那么它仅在满足以下条件时才有效:

  • 主项目的配置步骤假定外部项目使用 CMake 作为其构建系统。

  • 外部项目的安装命令实际运行。请注意,由于 `` 内部使用时间戳的方式,如果安装步骤依赖的任何内容不需要重新执行,则安装命令也可能不需要运行。

另请注意,`` 不会检查 `CMAKE_INSTALL_MODE` 环境变量是否在一次运行到下一次运行之间发生更改。

INSTALL_ENVIRONMENT_MODIFICATION <modification>...

版本 4.2 中添加。

指定应为安装步骤修改的环境变量。

设置一个(分号分隔的列表)环境变量和值,形式为 ``,其中 `` 是要修改的环境变量的区分大小写的名称。条目按属性值中指定的顺序考虑。`OP` 可以是以下之一:

  • reset:重置为未修改的值,忽略此条目之前对 `MYVAR` 的所有修改。请注意,这将把变量重置为 ENVIRONMENT 设置的值(如果已设置),否则重置为 CTest 执行其余部分的状态。

  • set:用 `VALUE` 替换 `MYVAR` 的当前值。

  • unset:取消设置 `MYVAR` 的当前值。

  • string_append:使用主机平台的路径列表分隔符(Windows 上为 `;`,其他地方为 `:`),将单个 `VALUE` 追加到 `MYVAR` 的当前值。

  • string_prepend:使用主机平台的路径列表分隔符(Windows 上为 `;`,其他地方为 `:`),将单个 `VALUE` 前置到 `MYVAR` 的当前值。

  • path_list_append:使用主机平台的路径列表分隔符(Windows 上为 `;`,其他地方为 `:`),将单个 `VALUE` 追加到 `MYVAR` 的当前值。

  • path_list_prepend:使用主机平台的路径列表分隔符(Windows 上为 `;`,其他地方为 `:`),将单个 `VALUE` 前置到 `MYVAR` 的当前值。

  • cmake_list_append:使用 `;` 作为分隔符,将单个 `VALUE` 追加到 `MYVAR` 的当前值。

  • cmake_list_prepend:使用 `;` 作为分隔符,将单个 `VALUE` 前置到 `MYVAR` 的当前值。

测试步骤选项

只有当提供了以下 `TEST_...` 选项之一时,才会定义测试步骤。

TEST_COMMAND <cmd>...

覆盖默认测试命令(支持 生成器表达式)。如果未给出此选项,测试步骤的默认行为是构建外部项目自身的 `test` 目标。此选项可以指定为 `` 为空字符串,这允许仍定义测试步骤,但它将无所作为。如果提供空字符串作为测试命令,请不要指定其他 `TEST_...` 选项,但如果不需要测试步骤目标,则最好完全省略所有 `TEST_...` 选项。

TEST_BEFORE_INSTALL <bool>

启用此选项时,测试步骤将在安装步骤之前执行。默认行为是测试步骤在安装步骤之后运行。

TEST_AFTER_INSTALL <bool>

此选项主要用作指示需要测试步骤但所有默认行为都已足够的方式。将此选项指定为布尔真值可确保定义测试步骤,并且它位于安装步骤之后。如果同时启用了 `TEST_BEFORE_INSTALL` 和 `TEST_AFTER_INSTALL`,则后者将被静默忽略。

TEST_EXCLUDE_FROM_MAIN <bool>

版本 3.2 中新增。

如果启用,主构建的默认 ALL 目标将不依赖于测试步骤。这可能是一种确保定义测试步骤但仅在手动请求时才调用的有用方法。这可能会导致自动为 `install` 或 `build` 步骤创建步骤目标。参见策略 CMP0114

TEST_ENVIRONMENT_MODIFICATION <modification>...

版本 4.2 中添加。

指定应为测试步骤修改的环境变量。

设置一个(分号分隔的列表)环境变量和值,形式为 ``,其中 `` 是要修改的环境变量的区分大小写的名称。条目按属性值中指定的顺序考虑。`OP` 可以是以下之一:

  • reset:重置为未修改的值,忽略此条目之前对 `MYVAR` 的所有修改。请注意,这将把变量重置为 ENVIRONMENT 设置的值(如果已设置),否则重置为 CTest 执行其余部分的状态。

  • set:用 `VALUE` 替换 `MYVAR` 的当前值。

  • unset:取消设置 `MYVAR` 的当前值。

  • string_append:使用主机平台的路径列表分隔符(Windows 上为 `;`,其他地方为 `:`),将单个 `VALUE` 追加到 `MYVAR` 的当前值。

  • string_prepend:使用主机平台的路径列表分隔符(Windows 上为 `;`,其他地方为 `:`),将单个 `VALUE` 前置到 `MYVAR` 的当前值。

  • path_list_append:使用主机平台的路径列表分隔符(Windows 上为 `;`,其他地方为 `:`),将单个 `VALUE` 追加到 `MYVAR` 的当前值。

  • path_list_prepend:使用主机平台的路径列表分隔符(Windows 上为 `;`,其他地方为 `:`),将单个 `VALUE` 前置到 `MYVAR` 的当前值。

  • cmake_list_append:使用 `;` 作为分隔符,将单个 `VALUE` 追加到 `MYVAR` 的当前值。

  • cmake_list_prepend:使用 `;` 作为分隔符,将单个 `VALUE` 前置到 `MYVAR` 的当前值。

输出日志选项

以下每个 `LOG_...` 选项都可以用来将相关步骤包装在一个脚本中,以捕获其输出到文件。日志文件将在 `LOG_DIR`(如果提供)或 `STAMP_DIR` 目录中创建,并带有特定于步骤的文件名。

LOG_DOWNLOAD <bool>

启用此选项时,将下载步骤的输出记录到文件中。

LOG_UPDATE <bool>

启用此选项时,将更新步骤的输出记录到文件中。

LOG_PATCH <bool>

3.14 版新增。

启用此选项时,将修补步骤的输出记录到文件中。

LOG_CONFIGURE <bool>

启用此选项时,将配置步骤的输出记录到文件中。

LOG_BUILD <bool>

启用此选项时,将构建步骤的输出记录到文件中。

LOG_INSTALL <bool>

启用此选项时,将安装步骤的输出记录到文件中。

LOG_TEST <bool>

启用此选项时,将测试步骤的输出记录到文件中。

LOG_MERGED_STDOUTERR <bool>

3.14 版新增。

启用此选项时,对于任何正在记录到文件的步骤,stdout 和 stderr 将被合并。

LOG_OUTPUT_ON_FAILURE <bool>

3.14 版新增。

此选项仅在启用了其他 `LOG_` 选项之一的情况下才有效果。如果对于启用了文件日志记录的步骤发生错误,并且 `LOG_OUTPUT_ON_FAILURE` 设置为 true,则该步骤的输出将打印到控制台。对于记录了大量输出的情况,可能只会在控制台打印该输出的末尾部分。

终端访问选项

3.4 版本新增。

在某些情况下,步骤可以被给予直接访问终端的权限。授予步骤访问终端的权限可能允许它接收终端输入(如果需要),例如用于未通过其他选项提供的身份验证详细信息。对于 Ninja 生成器,这些选项将步骤放置在 console 作业池 中。每个步骤都可以通过以下选项单独给予访问终端的权限:

USES_TERMINAL_DOWNLOAD <bool>

授予下载步骤访问终端的权限。

USES_TERMINAL_UPDATE <bool>

授予更新步骤访问终端的权限。

USES_TERMINAL_PATCH <bool>

在版本 3.23 中添加。

授予修补步骤访问终端的权限。

USES_TERMINAL_CONFIGURE <bool>

授予配置步骤访问终端的权限。

USES_TERMINAL_BUILD <bool>

授予构建步骤访问终端的权限。

USES_TERMINAL_INSTALL <bool>

授予安装步骤访问终端的权限。

USES_TERMINAL_TEST <bool>

授予测试步骤访问终端的权限。

目标选项

DEPENDS <targets>...

指定外部项目依赖的其他目标。其他目标将在执行外部项目的任何步骤之前更新。由于外部项目内部使用额外的自定义目标来处理每个步骤,因此 `DEPENDS` 选项是确保所有这些步骤都依赖于其他目标的最便捷方式。仅执行 ` )` 不会使任何步骤依赖于 ``。

EXCLUDE_FROM_ALL <bool>

启用此选项时,将外部项目排除在主构建的默认 ALL 目标之外。

STEP_TARGETS <step-target>...

为指定的步骤生成自定义目标。如果需要手动触发这些步骤或需要将它们用作其他目标的依赖项,则需要此选项。如果未指定此选项,则默认值将从 `EP_STEP_TARGETS` 目录属性中获取。请参阅下面的 `` 以进一步讨论此选项的影响。

INDEPENDENT_STEP_TARGETS <step-target>...

自 3.19 版本起弃用: 仅当策略 CMP0114 未设置为 NEW 时才允许此设置。

为指定的步骤生成自定义目标,并阻止这些目标应用通常的依赖项。如果未指定此选项,则默认值将取自 EP_INDEPENDENT_STEP_TARGETS 目录属性。此选项主要用于允许单独驱动各个步骤,例如用于 CDash 设置,其中每个步骤都应单独启动和报告,而不是作为一个整体构建。有关此选项效果的进一步讨论,请参阅下面的 ExternalProject_Add_StepTargets()

杂项选项

LIST_SEPARATOR <sep>

对于各种 ..._COMMAND 选项、CMAKE_ARGS..._ENVIRONMENT_MODIFICATION` 操作,ExternalProject 会将指定命令行中的 <sep> 替换为 ;。这可以用于确保命令在其中有一个字面的 ;,而直接使用将否则被解释为 CMake API 的参数分隔符。请注意,应选择分隔符以避免与序列的非列表分隔符用法混淆。例如,使用 LIST_SEPARATOR 允许将列表值传递给命令行上的 CMake 缓存变量。

ExternalProject_Add(example
  ... # Download options, etc.
  LIST_SEPARATOR ","
  CMAKE_ARGS "-DCMAKE_PREFIX_PATH:STRING=${first_prefix},${second_prefix}"
)
COMMAND <cmd>...

任何其他 ..._COMMAND 选项都可以通过在其后附加任意数量的 COMMAND ... 选项来附加其他命令(支持 生成器表达式)。例如:

ExternalProject_Add(example
  ... # Download options, etc.
  BUILD_COMMAND ${CMAKE_COMMAND} -E echo "Starting $<CONFIG> build"
  COMMAND       ${CMAKE_COMMAND} --build <BINARY_DIR> --config $<CONFIG>
  COMMAND       ${CMAKE_COMMAND} -E echo "$<CONFIG> build complete"
)

还应注意,每个构建步骤都是通过调用 ExternalProject_Add_Step() 来创建的。有关支持的某些选项的自动替换,请参阅该命令的文档。

获取项目属性

ExternalProject_Get_Property

函数 ExternalProject_Get_Property() 用于检索外部项目目标属性。

ExternalProject_Get_Property(<name> <prop1> [<prop2>...])

该函数将属性值存储在同名的变量中。属性名称对应于 ExternalProject_Add() 的关键字参数名称。例如,源目录可以这样检索:

ExternalProject_Get_property(myExtProj SOURCE_DIR)
message("Source dir of myExtProj = ${SOURCE_DIR}")

显式步骤管理

单独使用 ExternalProject_Add() 函数通常足以将外部项目集成到主构建中。某些场景需要额外的工作来实现期望的行为,例如添加自定义步骤或将步骤作为可手动触发的目标。 ExternalProject_Add_Step()ExternalProject_Add_StepTargets()ExternalProject_Add_StepDependencies 函数提供了实现此类步骤级功能所需的较低级别控制。

ExternalProject_Add_Step

函数 ExternalProject_Add_Step() 指定由先前调用 ExternalProject_Add() 定义的外部项目的其他自定义步骤。

ExternalProject_Add_Step(<name> <step> [<option>...])

<name> 与传递给 ExternalProject_Add() 的原始调用名称相同。指定的 <step> 不能是预定义步骤之一(mkdirdownloadupdatepatchconfigurebuildinstalltest)。支持的选项是:

COMMAND <cmd>...

此自定义步骤要执行的命令行(支持 生成器表达式)。可以多次重复此选项以指定按顺序执行的多个命令。

COMMENT "<text>..."

自定义步骤执行时要打印的文本。

DEPENDEES <step>...

此步骤依赖的其他步骤(自定义或预定义)。

DEPENDERS <step>...

其他依赖于此新自定义步骤的步骤(自定义或预定义)。

DEPENDS <file>...

此自定义步骤依赖的文件。

ENVIRONMENT_MODIFICATION <modification>...

版本 4.2 中添加。

指定在运行外部项目步骤中的命令时应修改的环境变量。

设置一个(分号分隔的列表)环境变量和值,形式为 ``,其中 `` 是要修改的环境变量的区分大小写的名称。条目按属性值中指定的顺序考虑。`OP` 可以是以下之一:

  • reset:重置为未修改的值,忽略此条目之前对 MYVAR 的所有修改。请注意,这将把变量重置为 ENVIRONMENT 设置的值(如果已设置),否则重置为 CTest 执行其余部分时的状态。

  • set:用 `VALUE` 替换 `MYVAR` 的当前值。

  • unset:取消设置 `MYVAR` 的当前值。

  • string_append:使用主机平台的路径列表分隔符(Windows 上为 `;`,其他地方为 `:`),将单个 `VALUE` 追加到 `MYVAR` 的当前值。

  • string_prepend:使用主机平台的路径列表分隔符(Windows 上为 `;`,其他地方为 `:`),将单个 `VALUE` 前置到 `MYVAR` 的当前值。

  • path_list_append:使用主机平台的路径列表分隔符(Windows 上为 `;`,其他地方为 `:`),将单个 `VALUE` 追加到 `MYVAR` 的当前值。

  • path_list_prepend:使用主机平台的路径列表分隔符(Windows 上为 `;`,其他地方为 `:`),将单个 `VALUE` 前置到 `MYVAR` 的当前值。

  • cmake_list_append:使用 `;` 作为分隔符,将单个 `VALUE` 追加到 `MYVAR` 的当前值。

  • cmake_list_prepend:使用 `;` 作为分隔符,将单个 `VALUE` 前置到 `MYVAR` 的当前值。

INDEPENDENT <bool>

3.19 版本新增。

指定此步骤是否独立于 ExternalProject_Add()DEPENDS 选项指定的外部依赖项。默认值为 FALSE。标记为独立的步骤只能依赖于其他标记为独立的步骤。请参阅策略 CMP0114

请注意,术语“独立”在此处的用法仅指独立于 DEPENDS 选项指定的外部目标,并且与步骤对其他步骤的依赖性是正交的。

如果通过 ExternalProject_Add()STEP_TARGETS 选项或通过 ExternalProject_Add_StepTargets() 函数为独立步骤创建了步骤目标,则该目标将不依赖于外部目标,但可能依赖于其他步骤的目标。

BYPRODUCTS <file>...

版本 3.2 中新增。

此自定义步骤将生成的文件,但后续构建可能或可能不更新其修改时间。在使用 Ninja 生成器时,可能还需要显式声明依赖项。此文件列表最终将作为 BYPRODUCTS 选项传递给用于内部实现自定义步骤的 add_custom_command(),该命令有其他文档。

ALWAYS <bool>

启用后,此选项指定自定义步骤应始终运行(即,它始终被认为已过时)。

JOB_SERVER_AWARE <bool>

版本 3.28 新增。

指定自定义步骤能够感知 GNU Make 作业服务器。有关详细信息,请参阅 add_custom_command() 文档中其 JOB_SERVER_AWARE 选项。

EXCLUDE_FROM_MAIN <bool>

启用后,此选项指定外部项目的主目标不依赖于自定义步骤。这可能会为该步骤依赖的步骤自动创建步骤目标。请参阅策略 CMP0114

WORKING_DIRECTORY <dir>

指定在运行自定义步骤的命令之前设置的工作目录。如果未指定此选项,则目录将是调用 ExternalProject_Add_Step()CMAKE_CURRENT_BINARY_DIR 的值。

LOG <bool>

如果设置为 true,这将导致自定义步骤的输出被捕获到外部项目的 LOG_DIR(如果已提供)或 STAMP_DIR 中的文件中。

USES_TERMINAL <bool>

如果启用,这可以使自定义步骤能够直接访问终端。

将处理每个标准和自定义步骤的命令行、注释、工作目录和副产品,以替换 <SOURCE_DIR><SOURCE_SUBDIR><BINARY_DIR><INSTALL_DIR> <TMP_DIR><DOWNLOAD_DIR><DOWNLOADED_FILE> 令牌及其在 ExternalProject_Add() 的原始调用中定义的相应属性值。

3.3 版本新增: 令牌替换已扩展到副产品。

3.11 版本新增: <DOWNLOAD_DIR> 替换令牌。

ExternalProject_Add_StepTargets

函数 ExternalProject_Add_StepTargets() 为列出的步骤生成目标。每个创建的目标名称将为 <name>-<step> 的形式。

ExternalProject_Add_StepTargets(<name> <step1> [<step2>...])

为步骤创建目标允许将其用作另一个目标的依赖项或手动触发。为特定步骤拥有目标还允许通过在构建命令行上指定目标来独立驱动它们。例如,您可能要提交到一个子项目仪表板,您希望驱动构建的配置部分,然后提交到仪表板,然后是构建部分,最后是测试。如果您调用一个依赖于步骤依赖链中间步骤的自定义目标,那么所有之前的步骤也将运行,以确保一切都是最新的。

在内部,ExternalProject_Add() 调用 ExternalProject_Add_Step() 来创建每个步骤。如果指定了任何 STEP_TARGETS,那么在调用 ExternalProject_Add_Step() 之后也会调用 ExternalProject_Add_StepTargets()。即使某个步骤未在 STEP_TARGETS 选项中提及,仍然可以稍后调用 ExternalProject_Add_StepTargets() 来手动为该步骤定义一个目标。

ExternalProject_Add() 使用 STEP_TARGETS 选项通常是确保为特定感兴趣的步骤创建目标的最简单方法。对于自定义步骤,如果也要为该自定义步骤创建目标,则必须显式调用 ExternalProject_Add_StepTargets()。这两种选项的替代方法是填充 EP_STEP_TARGETS 目录属性。它充当步骤目标选项的默认值,并且可以在定义多个外部项目时避免重复指定同一组步骤目标。

自 3.19 版本起添加: 如果 CMP0114 设置为 NEW,则步骤目标将完全负责持有实现其步骤的自定义命令。由 ExternalProject_Add 创建的主目标依赖于步骤目标,步骤目标相互依赖。目标级依赖关系匹配自定义命令为每个步骤使用的文件级依赖关系。使用 ExternalProject_Add_Step()INDEPENDENT 选项创建的步骤的目标不依赖于 ExternalProject_Add()DEPENDS 选项指定的外部目标。预定义步骤 mkdirdownloadupdatepatch 是独立的。

如果 CMP0114 不是 NEW,则提供以下已弃用的行为:

  • 可以在 <name> 之后、第一个步骤之前指定一个已弃用的 NO_DEPENDS 选项。如果指定了 NO_DEPENDS 选项,则步骤目标将不依赖于外部项目的依赖项(即,不依赖于 ExternalProject_Add() 创建的 <name> 自定义目标的任何依赖项)。这通常对 downloadupdatepatch 步骤是安全的,因为它们通常不需要更新和构建依赖项。然而,对其他预定义步骤中的任何一个使用 NO_DEPENDS 可能会破坏并行构建。仅在确定命名的步骤确实没有依赖项时才使用 NO_DEPENDS。对于自定义步骤,请考虑自定义命令是否需要配置、构建和安装依赖项。

  • ExternalProject_Add() 使用 INDEPENDENT_STEP_TARGETS 选项,或使用 EP_INDEPENDENT_STEP_TARGETS 目录属性,会告诉该函数内部调用 ExternalProject_Add_StepTargets(),并为指定的步骤使用 NO_DEPENDS 选项。

ExternalProject_Add_StepDependencies

版本 3.2 中新增。

函数 ExternalProject_Add_StepDependencies() 可用于向步骤添加依赖项。添加的依赖项必须是 CMake 已知晓的目标(这些目标可以是普通的 executable 或 library 目标、自定义目标,甚至是另一个外部项目的步骤目标)。

ExternalProject_Add_StepDependencies(<name> <step> <target1> [<target2>...])

此函数会仔细设置目标和文件级别的依赖项,并确保并行构建不会中断。每当为 ExternalProject 模块生成的步骤目标之一添加依赖项时,都应使用此函数,而不是 add_dependencies()

示例

以下示例显示了如何从 github 下载并构建一个名为 FooBar 的假设项目。

include(ExternalProject)
ExternalProject_Add(foobar
  GIT_REPOSITORY    git@github.com:FooCo/FooBar.git
  GIT_TAG           origin/release/1.2.3
)

为便于举例,还定义了第二个名为 SecretSauce 的假设外部项目,它从 Web 服务器下载。提供了两个 URL,以便在可用时利用更快的内部网络,并回退到较慢的外部服务器。该项目是一个典型的 Makefile 项目,没有配置步骤,因此会覆盖一些默认命令。构建仅需要构建 sauce 目标。

find_program(MAKE_EXE NAMES gmake nmake make)
ExternalProject_Add(secretsauce
  URL               http://intranet.somecompany.com/artifacts/sauce-2.7.tgz
                    https://www.somecompany.com/downloads/sauce-2.7.zip
  URL_HASH          MD5=d41d8cd98f00b204e9800998ecf8427e
  CONFIGURE_COMMAND ""
  BUILD_COMMAND     ${MAKE_EXE} sauce
)

假设 secretsauce 的构建步骤要求 foobar 必须已经构建。这可以这样强制执行:

ExternalProject_Add_StepDependencies(secretsauce build foobar)

另一种选择是为 foobar 的构建步骤创建一个自定义目标,并让 secretsauce 依赖于该目标,而不是整个 foobar 项目。这意味着 foobar 只需要构建,而不需要运行其 install 或 test 步骤,secretsauce 就可以构建。依赖项也可以与 secretsauce 项目一起定义。

ExternalProject_Add_StepTargets(foobar build)
ExternalProject_Add(secretsauce
  URL               http://intranet.somecompany.com/artifacts/sauce-2.7.tgz
                    https://www.somecompany.com/downloads/sauce-2.7.zip
  URL_HASH          MD5=d41d8cd98f00b204e9800998ecf8427e
  CONFIGURE_COMMAND ""
  BUILD_COMMAND     ${MAKE_EXE} sauce
  DEPENDS           foobar-build
)

而不是调用 ExternalProject_Add_StepTargets(),该目标可以与 foobar 项目本身一起定义。

ExternalProject_Add(foobar
  GIT_REPOSITORY git@github.com:FooCo/FooBar.git
  GIT_TAG        origin/release/1.2.3
  STEP_TARGETS   build
)

如果许多外部项目应该具有相同的步骤目标集,则设置目录属性可能更方便。通过在调用 ExternalProject_Add() 创建外部项目之前设置 EP_STEP_TARGETS 目录属性,可以自动创建 build 步骤目标。

set_property(DIRECTORY PROPERTY EP_STEP_TARGETS build)

最后,假设 secretsauce 提供了一个名为 makedoc 的脚本,该脚本可用于生成其自身的文档。进一步假设该脚本期望输出目录作为唯一参数,并且应该从 secretsauce 源目录运行。可以这样定义一个自定义步骤和一个触发脚本的自定义目标:

ExternalProject_Add_Step(secretsauce docs
  COMMAND           <SOURCE_DIR>/makedoc <BINARY_DIR>
  WORKING_DIRECTORY <SOURCE_DIR>
  COMMENT           "Building secretsauce docs"
  ALWAYS            TRUE
  EXCLUDE_FROM_MAIN TRUE
)
ExternalProject_Add_StepTargets(secretsauce docs)

然后可以从主构建中这样触发自定义步骤:

cmake --build . --target secretsauce-docs