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>

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

如果未指定上述任何 ..._DIR 选项,则它们的默认值计算如下。如果给定了 PREFIX 选项或设置了 EP_PREFIX 目录属性,则外部项目将在指定的 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 目录属性,则外部项目的组件将存储在指定的 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>

如果未指定 PREFIXEP_PREFIXEP_BASE,则默认值是将 PREFIX 设置为 <name>-prefix。相对路径相对于调用 CMAKE_CURRENT_BINARY_DIR 的点进行解释 ExternalProject_Add()

下载步骤选项

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

DOWNLOAD_COMMAND <cmd>...

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

URL

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

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

在 3.7 版本中更改: 允许多个 URL。

URL_HASH <algo>=<hashValue>

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

URL_MD5 <md5>

等同于 URL_HASH MD5=<md5>

DOWNLOAD_NAME <fname>

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

DOWNLOAD_EXTRACT_TIMESTAMP <bool>

在 3.24 版本中添加。

当指定为真值时,解压文件的的时间戳将与存档中的时间戳匹配。当为假值时,解压文件的的时间戳将反映执行解压的时间。如果下载 URL 更改,则基于存档中的时间戳可能会导致依赖目标在可能应该重建时没有重建。因此,除非文件时间戳在某些方面对项目很重要,否则请为此选项使用假值。如果未给出 DOWNLOAD_EXTRACT_TIMESTAMP,则默认值为 false。请参阅策略 CMP0135

DOWNLOAD_NO_EXTRACT <bool>

在 3.6 版本中添加。

允许通过为此选项传递布尔真值来禁用下载步骤的解压部分。如果未给出此选项,则如果需要,将自动解压下载的内容。如果已禁用解压,则已下载文件的完整路径在后续步骤中可用作 <DOWNLOADED_FILE>,或者使用 ExternalProject_Get_Property() 命令作为属性 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 配置选项确定。

在 3.6 版本中更改: 以前,此选项不适用于 git clone 调用。

在 3.30 版本中更改: 以前,未检查 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 级别为 OPTIONALREQUIRED,则指定备用 .netrc 文件,而不是主目录中的文件。如果未指定此选项,则将使用 CMAKE_NETRC_FILE 变量的值(请参阅 file(DOWNLOAD)

在 3.1 版本中添加: 添加了对 tbz2.tar.xz.txz.7z 扩展名的支持。

Git

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

GIT_REPOSITORY <url>

git 仓库的 URL。git 命令理解的任何 URL 都可以使用。

在 3.27 版本中更改: 相对 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 子模块都将被更新。

在 3.16 版本中更改: CMP0097 设置为 NEW 时,如果此值设置为空字符串,则不会初始化或更新子模块。

GIT_SUBMODULES_RECURSE <bool>

在 3.17 版本中添加。

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

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 <option>,并且每个选项都必须采用 key=value 形式。

GIT_REMOTE_UPDATE_STRATEGY <strategy>

在 3.18 版本中添加。

GIT_TAG 指的是远程分支时,可以使用此选项来指定更新步骤的行为方式。<strategy> 必须是以下之一

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 指的是有效的引用,则更新应始终成功,除非存在无法成功弹出的未提交更改。

可以设置变量 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())并手动调用。如果您想允许开发人员在断开网络连接时构建项目,这将非常有用(尽管下载步骤可能仍然需要网络)。

版本 3.27 中变更: UPDATE_DISCONNECTED 为真时,如果更新或下载步骤的任何详细信息发生更改,则将执行更新步骤。 此外,如果使用 git 下载/更新方法,更新逻辑将被修改为跳过联系远程仓库的尝试。 如果 GIT_TAG 提及本地未知的引用,更新步骤将因致命错误而停止。

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

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

Patch 步骤选项

PATCH_COMMAND <cmd>...

指定在更新后修补源文件的自定义命令。 默认情况下,未定义补丁命令。 请注意,定义一个能够可靠执行的适当补丁命令可能非常困难,特别是对于像 git 这样的下载方法,其中更改 GIT_TAG 不会丢弃先前补丁的更改,但在更新到新标签后,补丁命令将再次被调用。

Configure 步骤选项

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

CONFIGURE_COMMAND <cmd>...

默认的配置命令运行 CMake,并带有一些基于主项目的选项。 添加的选项通常只是那些使用与主项目相同的生成器所需的选项,但是可以给出 CMAKE_GENERATOR 选项来覆盖此设置。 项目负责添加它想要从主项目重用或以其他方式指定的任何工具链详细信息、标志或其他设置(请参阅下面的 CMAKE_ARGSCMAKE_CACHE_ARGSCMAKE_CACHE_DEFAULT_ARGS)。

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

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 选项)。

版本 3.3 中新增: 参数可以使用 generator expressions

CMAKE_CACHE_ARGS <arg>...

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

版本 3.3 中新增: 参数可以使用 generator expressions

CMAKE_CACHE_DEFAULT_ARGS <arg>...

在 3.2 版本中添加。

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

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

SOURCE_SUBDIR <dir>

在 3.7 版本中添加。

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

版本 3.14 中新增: 当启用 BUILD_IN_SOURCE 选项时,CONFIGURE_SUBDIR 用于指向源树中的备用目录。

CONFIGURE_HANDLED_BY_BUILD <bool>

在版本 3.20 中添加。

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

Build 步骤选项

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

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

BUILD_COMMAND <cmd>...

覆盖默认的构建命令(支持 generator expressions)。 如果未提供此选项,则将选择默认的构建命令,以便以最合适的方式与主构建集成(例如,对于 Makefile 生成器使用递归 make,或者如果项目使用 CMake 构建,则使用 cmake --build)。 可以将此选项指定为空字符串作为命令,以使构建步骤不执行任何操作。

BUILD_IN_SOURCE <bool>

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

BUILD_ALWAYS <bool>

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

BUILD_BYPRODUCTS <file>...

在 3.2 版本中添加。

指定将由构建命令生成的文件,但这些文件的修改时间可能会或可能不会被后续构建更新。 当使用 Ninja 生成器时,这也可能是显式声明依赖项所必需的。 这些最终作为 BYPRODUCTS 传递给构建步骤自身对 add_custom_command() 的底层调用,该调用具有其他文档。

BUILD_JOB_SERVER_AWARE <bool>

在版本 3.28 中添加。

指定构建步骤可以识别 GNU Make job server。 有关详细信息,请参阅 add_custom_command() 文档中的 JOB_SERVER_AWARE 选项。 此选项仅在指定显式 BUILD_COMMAND 时相关。

Install 步骤选项

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

INSTALL_COMMAND <cmd>...

外部项目自身的安装步骤作为主项目的构建的一部分被调用。 它在外部项目的构建步骤之后完成,并且可能在外部项目的测试步骤之前或之后完成(请参阅下面的 TEST_BEFORE_INSTALL 选项)。 外部项目的安装规则不是主项目的安装规则的一部分,因此如果外部项目的任何内容应作为主构建的一部分安装,则需要在主构建中将这些指定为额外的 install() 命令。 默认的安装步骤构建外部项目的 install 目标,但是可以使用此选项的自定义命令覆盖此设置(支持 generator expressions)。 将空字符串作为 <cmd> 传递将使安装步骤不执行任何操作。

INSTALL_BYPRODUCTS <file>...

在版本 3.26 中添加。

指定将由安装命令生成的文件,但这些文件的修改时间可能会或可能不会被后续安装更新。 当使用 Ninja 生成器时,这也可能是显式声明依赖项所必需的。 这些最终作为 BYPRODUCTS 传递给安装步骤自身对 add_custom_command() 的底层调用,该调用具有其他文档。

INSTALL_JOB_SERVER_AWARE <bool>

在版本 4.0 中添加。

指定安装步骤可以识别 GNU Make job server。 有关详细信息,请参阅 add_custom_command() 文档中的 JOB_SERVER_AWARE 选项。 此选项仅在指定显式 INSTALL_COMMAND 时相关。

注意

如果在构建主项目时设置了 CMAKE_INSTALL_MODE 环境变量,则只有在满足以下条件时才会生效

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

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

另请注意,ExternalProject 不检查 CMAKE_INSTALL_MODE 环境变量是否从一次运行更改为另一次运行。

Test 步骤选项

仅当提供以下 TEST_... 选项中的至少一个时,才定义测试步骤。

TEST_COMMAND <cmd>...

覆盖默认的测试命令(支持 generator expressions)。 如果未提供此选项,则测试步骤的默认行为是构建外部项目自己的 test 目标。 可以将此选项指定为 <cmd> 空字符串,这允许仍然定义测试步骤,但它将不执行任何操作。 如果提供空字符串作为测试命令,请勿指定任何其他 TEST_... 选项,但如果不需要测试步骤目标,则最好完全省略所有 TEST_... 选项。

TEST_BEFORE_INSTALL <bool>

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

TEST_AFTER_INSTALL <bool>

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

TEST_EXCLUDE_FROM_MAIN <bool>

在 3.2 版本中添加。

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

Output Logging 选项

以下每个 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_<step> 选项时,此选项才有效。 如果启用了文件日志记录的步骤发生错误,则如果 LOG_OUTPUT_ON_FAILURE 设置为 true,则该步骤的输出将打印到控制台。 对于记录了大量输出的情况,可能只会将该输出的末尾打印到控制台。

Terminal Access 选项

在版本 3.4 中添加。

在某些情况下,步骤可以直接访问终端。 允许步骤访问终端可以使其在需要时接收终端输入,例如用于其他选项未提供的身份验证详细信息。 使用 Ninja 生成器,这些选项将步骤放置在 console job pool 中。 可以通过以下选项单独为每个步骤授予对终端的访问权限

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>

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

Target 选项

DEPENDS <targets>...

指定外部项目所依赖的其他目标。 在执行外部项目的任何步骤之前,将使其他目标保持最新。 由于外部项目在内部为每个步骤使用额外的自定义目标,因此 DEPENDS 选项是确保所有这些步骤都依赖于其他目标的最方便方法。 仅仅执行 add_dependencies(<name> <targets>) 不会使任何步骤依赖于 <targets>

EXCLUDE_FROM_ALL <bool>

启用后,此选项会将外部项目从主构建的默认 ALL 目标中排除。

STEP_TARGETS <step-target>...

为指定的步骤生成自定义目标。 如果需要手动触发步骤,或者需要将步骤用作其他目标的依赖项,则这是必需的。 如果未指定此选项,则默认值取自 EP_STEP_TARGETS 目录属性。 有关此选项效果的进一步讨论,请参阅下面的 ExternalProject_Add_StepTargets()

INDEPENDENT_STEP_TARGETS <step-target>...

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

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

Miscellaneous 选项

LIST_SEPARATOR <sep>

对于各种 ..._COMMAND 选项以及 CMAKE_ARGSExternalProject 将把指定的命令行中的 <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 ... 选项来附加额外的命令(支持 generator expressions)。 例如

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() 创建的。 有关某些选项支持的自动替换,请参阅该命令的文档。

Obtaining Project Properties

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}")

Explicit Step Management

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>...

此自定义步骤要执行的命令行(支持 generator expressions)。可以多次重复此选项以指定要按顺序执行的多个命令。

COMMENT "<text>..."

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

DEPENDEES <step>...

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

DEPENDERS <step>...

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

DEPENDS <file>...

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

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>

如果设置,这将导致来自自定义步骤的输出被捕获到外部项目的 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 目录属性告诉函数使用指定步骤的 NO_DEPENDS 选项在内部调用 ExternalProject_Add_StepTargets()

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 只需要构建,在可以构建 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
)

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

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