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 目录属性,则外部项目将在指定前缀下生成并安装

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>

如未指定 PREFIXEP_PREFIXEP_BASE,那么默认设置 PREFIX<name>-prefix。相对路径根据在调用 ExternalProject_Add()CMAKE_CURRENT_BINARY_DIR 进行解释。

下载步骤选项

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

DOWNLOAD_COMMAND <cmd>...

覆盖用于下载步骤的命令(generator expressions 受支持)。如果指定了此选项,则会忽略所有其他下载选项。为 <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 中添加。

当指定为 true 值时,提取文件的时间戳将匹配存档中的时间戳。当为 false 时,提取文件的时间戳将反映执行提取操作的时间。如果下载 URL 发生更改,基于存档中的时间戳可能导致依赖目标未在需要时重建。因此,除非文件时间戳以某种方式对项目至关重要,否则请针对此选项使用 false 值。如果没有提供 DOWNLOAD_EXTRACT_TIMESTAMP ,则默认值为 false。请参见策略 CMP0135

DOWNLOAD_NO_EXTRACT <bool>

在版本 3.6 中添加。

通过为此选项传递布尔 true 值,可以禁用下载步骤的提取部分。如果没有提供此选项,则在需要时将自动解压缩下载的内容。如果已禁用提取,则以下载文件 <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,请为 home 目录中的那个指定一个备用 .netrc 文件。如果未指定此选项,将改为使用 CMAKE_NETRC_FILE 变量的值(请参阅 file(DOWNLOAD)

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

Git

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

GIT_REPOSITORY <url>

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

已在版本 3.27 中更改: 将根据父项目的远程解析相对 URL,但需要遵守 CMP0150。请参阅策略文档以了解如何选择远程的,其中包括可能导致远程选择失败的情况。本地文件系统远程始终应使用绝对路径。

GIT_TAG <tag>

Git 分支名称、标签或提交哈希值。请注意,通常应将分支名称和标签指定为远程名称(即 origin/myBranch 而不是 myBranch)。这样可以确保如果远程端移动其标签或重新设置分支或重写历史记录,仍会正确更新本地克隆。但是,通常来说,由于多种原因,应优先指定一个提交哈希值

  • 如果本地克隆已具有对应于散列值的提交,则无需在每次重新运行 CMake 时执行 git fetch 来检查更改的情况。如果正在使用许多外部项目,则这会导致显著加速。

  • 使用特定哈希值确保主要项目自己的历史记录可以完全追溯到外部项目演变中的特定点。如果改用分支或标签名称,那么签出主要项目的特定提交并不一定将整个构建固定在外部项目的生命周期的特定点上。缺乏此类确定性行为导致主要项目的可追溯性和可重复性降低。

如果已启用 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 版中添加。

通过将 --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 的配置选项列表。列出的每个选项都将转化成其自己的 --config <option>git clone 命令行中,每个选项都必须采用 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 位置创建一个带注释的标记,然后检出 GIT_TAG,就像 CHECKOUT 策略一样。存储在带注释的标记上的消息将提供有关尝试了什么的信息,并且标记名称将包含时间戳,以便每次运行失败都会添加一个新标记。此策略确保不会丢失任何更改,但如果 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 checkout 和 update 命令。

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 不引用特定提交),外部项目的源代码将更新。

UPDATE_COMMAND <cmd>...

使用自定义命令覆盖下载方法的更新步骤。该命令可以使用 generator expressions

UPDATE_DISCONNECTED <bool>

版本 3.2 中已添加。

启用此选项后,将跳过更新步骤(但下面会介绍已更改行为,其中并不适用)。它不会阻止下载步骤。仍可将更新步骤添加为步骤目标(参见 ExternalProject_Add_StepTargets()),并手动调用它。当你希望允许开发者在与网络断开连接时构建项目时,此方法非常有用(虽然网络仍然可能用于下载步骤)。

版本 3.27 中已更改: UPDATE_DISCONNECTED 为 true 时,若更新或下载步骤的任何详细信息发生更改,将执行更新步骤。此外,如果使用 git 下载/更新方法,将修改更新逻辑,以跳过联系远程的尝试。如果 GIT_TAG 提到本地未知的引用的,更新步骤将停止并显示致命错误。

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

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

补丁步骤选项

PATCH_COMMAND <cmd>...

指定更新后用于修补源的自定义命令。默认情况下,没有定义补丁命令。请注意,定义一个在各种情况下都能稳健执行的合适补丁命令可能相当困难,尤其是对于诸如 git 这样的下载方法,其中更改 GIT_TAG 不会放弃之前补丁的更改,但会在更新到新标签后再次调用该补丁命令。

配置步骤选项

下载和更新步骤后,会运行配置步骤。默认情况下,外部项目将假定为 CMake 项目,但必要时可以将其覆盖。

CONFIGURE_COMMAND <cmd>...

默认配置命令基于主项目运行 CMake 并增加几个选项。所添加的选项通常只是那些需要使用与主项目相同的生成器才能使用的选项,但可以通过 CMAKE_GENERATOR 选项进行覆盖。该项目负责添加它想要从主项目重用或以其他方式指定的任何工具链详细信息、标志或其他设置(请参阅以下 CMAKE_ARGSCMAKE_CACHE_ARGSCMAKE_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)。

在 3.3 版本中添加: 参数可以使用 generator expressions

CMAKE_CACHE_ARGS <arg>...

这是指定缓存变量的另一种方式,当命令行长度问题可能成为问题时。这些参数预计采用 -Dvar:STRING=value 形式,然后将其转换为带有使用 FORCE 选项的 CMake set() 命令。这些 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 选项时,BUILD_COMMAND 用于指向源代码树中的备用目录。

CONFIGURE_HANDLED_BY_BUILD <bool>

在 3.20 版本中添加。

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

构建步骤选项

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

如果主项目和外部项目都使用 make 作为构建工具,则会使用 $(MAKE) 以递归 make 的方式调用外部项目的构建步骤。此方法会从主项目将一些构建工具设置传至外部项目。如果主项目和外部项目中任何一个未使用 make,则除了由配置步骤建立的设置外,不会将构建工具设置传至外部项目(例如,在主项目中运行 ninja -v 时,不会将 -v 传至外部项目的构建步骤,即使该项目也使用 ninja 作为其构建工具)。

BUILD_COMMAND <cmd>...

覆盖默认构建命令(生成器 表达式 获得支持)。如果未提供此选项,系统会选择默认构建命令以最合适的方式与主版本集成(例如,对于 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 任务服务器。有关详细信息,请参阅 add_custom_command()JOB_SERVER_AWARE 选项的文档。当指定明确的 BUILD_COMMAND 时,此选项才相关。

安装步骤选项

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

INSTALL_COMMAND <cmd>...

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

INSTALL_BYPRODUCTS <file>...

在版本 3.26 中添加。

指定将由 `install` 命令生成的文件,但后续安装是否会更改该文件修改时间则不确定。使用 Ninja 生成器时,可能还需要显式声明依赖关系。这些依赖关系最终作为 BYPRODUCTS 传递到安装步骤自己的底层调用 add_custom_command(),其中有其他文档。

注意

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

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

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

另请注意,ExternalProject 不会检查 CMAKE_INSTALL_MODE 环境变量是否在每次运行之间发生变化。

测试步骤选项

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

TEST_COMMAND <cmd>...

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

TEST_BEFORE_INSTALL <bool>

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

TEST_AFTER_INSTALL <bool>

此选项主要用作指示需要测试步骤但所有默认行为已足够的一种方式。使用布尔真值指定此选项可确保定义了测试步骤以及该步骤在安装步骤之后执行。如果启用 TEST_BEFORE_INSTALLTEST_AFTER_INSTALL,则后者将被忽略。

TEST_EXCLUDE_FROM_MAIN <bool>

版本 3.2 中已添加。

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

输出日志记录选项

以下每个 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,该步骤的输出将打印到控制台。对于记录大量输出的情况,仅该输出的末尾可能会打印到控制台。

终端访问选项

在 3.4 版中添加。

在某些情况下,可以为步骤赋予对终端的直接访问权限。为步骤提供对终端的访问权限后,它可以(如果需要)接收终端输入,例如此选项未提供的身份验证详细信息。通过 Ninja 生成器,这些选项会将步骤放在 console 作业池 中。可以通过以下选项为每个步骤单独赋予对终端的访问权限

USES_TERMINAL_DOWNLOAD <bool>

让下载步骤访问终端。

USES_TERMINAL_UPDATE <bool>

让更新步骤访问终端。

USES_TERMINAL_PATCH <bool>

在 3.23 版中添加。

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

USES_TERMINAL_CONFIGURE <布尔值>

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

USES_TERMINAL_BUILD <布尔值>

授予生成步骤对终端的访问权限。

USES_TERMINAL_INSTALL <布尔值>

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

USES_TERMINAL_TEST <布尔值>

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

目标选项

DEPENDS <目标>...

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

EXCLUDE_FROM_ALL <布尔值>

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

STEP_TARGETS <步骤目标>...

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

INDEPENDENT_STEP_TARGETS <步骤目标>...

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

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

杂项选项

LIST_SEPARATOR <分隔符>

对于各种 ..._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 ... 选项来附加其他命令 (生成器 表达式 受支持)。例如

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

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

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>

启用此选项时,指定外部项目的 main 目标不依赖于自定义步骤。这可能导致为此步骤依赖的步骤自动创建步骤目标。见策略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。对于自定义步骤,请考虑自定义命令是否需要对依赖项进行配置、构建和安装。

  • INDEPENDENT_STEP_TARGETS 适用于 ExternalProject_Add() 选项,或 EP_INDEPENDENT_STEP_TARGETS 目录属性,指示此函数内部使用 NO_DEPENDS 选项调用 ExternalProject_Add_StepTargets()

ExternalProject_Add_StepDependencies

版本 3.2 中已添加。

ExternalProject_Add_StepDependencies() 函数可用于向步骤添加依赖关系。添加的依赖关系必须是 CMake 已知的目标(这些目标可以是普通可执行或库目标、自定义目标或甚至其他外部项目的步骤目标)

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

此函数负责设置目标和文件级依赖关系,并将确保并行构建不会中断。每当为 ExternalProject 模块生成的某个步骤目标添加依赖关系时,都应使用此函数代替 add_dependencies()

示例

以下示例展示了如何从 Github 下载并构建名为 FooBar 的虚拟项目

include(ExternalProject)
ExternalProject_Add(foobar
  GIT_REPOSITORY    [email protected]:FooCo/FooBar.git
  GIT_TAG           origin/release/1.2.3
)

为了示例,还定义另一个来自网络服务器的虚拟外部项目,称为 SecretSauce。提供两个 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
)

不要调用 ExternalProject_Add_StepTargets(),目标可以和 foobar 项目一起定义

ExternalProject_Add(foobar
  GIT_REPOSITORY [email protected]: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