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

覆寫用於下載步驟的命令(支援 產生器 運算式)。如果指定此選項,則會忽略所有其他下載選項。為 <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 中新增。

當指定為真值時,解壓縮檔案的時間戳記將與封存中的時間戳記相符。當為 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 <秒數>

在版本 3.19 中新增。

在一段非活動時間後終止操作。

HTTP_USERNAME <使用者名稱>

在版本 3.7 中新增。

如果需要驗證,則為下載操作的使用者名稱。

HTTP_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 <布林值>

指定是否應針對 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 <檔案>

指定如果啟用 TLS_VERIFY,則要使用的自訂憑證授權檔案。如果未指定此選項,則會改為使用 CMAKE_TLS_CAINFO 變數的值(請參閱 file(DOWNLOAD)

NETRC <層級>

在版本 3.11 中新增。

指定是否要將 .netrc 檔案用於操作。如果未指定此選項,則會改為使用 CMAKE_NETRC 變數的值(請參閱 file(DOWNLOAD))。有效的層級為

IGNORED

將忽略 .netrc 檔案。這是預設值。

OPTIONAL

.netrc 檔案是可選的,並且優先使用 URL 中的資訊。將掃描該檔案以尋找 URL 中未指定的任何資訊。

REQUIRED

需要 .netrc 檔案,並且忽略 URL 中的資訊。

NETRC_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 <網址>

git 儲存庫的 URL。可以使用 git 命令可理解的任何 URL。

在版本 3.27 中變更: 相對 URL 將根據父專案的遠端解析,但須遵守 CMP0150。請參閱政策文件,了解如何選取遠端,包括遠端選取可能會失敗的情況。本機檔案系統遠端應始終使用絕對路徑。

GIT_TAG <標籤>

Git 分支名稱、標籤或提交雜湊值。請注意,分支名稱和標籤通常應指定為遠端名稱(即 origin/myBranch 而不是單純的 myBranch)。這可確保如果遠端結束時其標籤已移動或分支已重新設定基準或重寫歷史記錄,則本機複製仍會正確更新。不過,一般而言,出於多種原因,應優先指定提交雜湊值。

  • 如果本機複製已具有與雜湊值對應的提交,則每次重新執行 CMake 時,都無需執行 git fetch 來檢查變更。如果正在使用許多外部專案,則這可能會導致顯著的加速。

  • 使用特定的 git 雜湊值可確保主專案本身的歷史記錄完全可追溯到外部專案發展的特定點。如果改為使用分支或標籤名稱,則檢查主專案的特定提交並不一定會將整個建置釘選到外部專案生命週期的特定點。缺少這種確定性行為會導致主專案失去可追溯性和重複性。

如果啟用 GIT_SHALLOW,則 GIT_TAG 僅適用於分支名稱和標籤。不允許使用提交雜湊值。

請注意,如果未提供,則 GIT_TAG 預設為 master,而不是預設的 Git 分支名稱。

GIT_REMOTE_NAME <名稱>

遠端的選擇性名稱。如果未指定此選項,則預設為 origin

GIT_SUBMODULES <模組>...

也應更新的特定 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 的配置選項清單。列出的每個選項都將在 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 為 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 選項)。

在版本 3.3 中新增:引數可以使用 產生器運算式

CMAKE_CACHE_ARGS <arg>...

這是指定快取變數的另一種方式,可能會發生命令列長度問題。引數預期採用 -Dvar:STRING=value 格式,然後將其轉換為 CMake set() 命令,並使用 FORCE 選項。這些 set() 命令會寫入預先載入的指令碼,然後使用 cmake -C 命令列選項套用。

在版本 3.3 中新增:引數可以使用 產生器運算式

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 的 job server。請參閱 add_custom_command() 文件中關於其 JOB_SERVER_AWARE 選項的詳細資訊。此選項僅在指定明確的 BUILD_COMMAND 時相關。

安裝步驟選項

如果組態步驟假設外部專案使用 CMake 作為其建置系統,則安裝步驟也會如此。否則,安裝步驟將假設基於 Makefile 的建置,並僅執行 make install 作為預設建置步驟。如果需要,可以使用自訂安裝命令覆寫此行為。

INSTALL_COMMAND <cmd>...

外部專案自身的安裝步驟會作為主專案建置的一部分被調用。它會在外部專案的建置步驟之後執行,並且可能在外部專案的測試步驟之前或之後執行(請參閱下方的 TEST_BEFORE_INSTALL 選項)。外部專案的安裝規則不是主專案安裝規則的一部分,因此如果外部專案的任何內容應該作為主建置的一部分安裝,則需要在主建置中指定這些內容作為額外的 install() 命令。預設安裝步驟會建置外部專案的 install 目標,但可以使用此選項以自訂命令覆寫此行為(支援 產生器 表達式)。將空字串作為 <cmd> 傳遞會使安裝步驟不做任何事。

INSTALL_BYPRODUCTS <file>...

於版本 3.26 新增。

指定由安裝命令產生,但後續安裝可能不會更新其修改時間的檔案。當使用 Ninja 產生器時,可能也需要明確宣告相依性。這些最終會以 BYPRODUCTS 的形式傳遞至安裝步驟本身對 add_custom_command() 的底層呼叫,該命令有額外的文件說明。

注意

如果在建置主專案時設定了 CMAKE_INSTALL_MODE 環境變數,則僅在滿足以下條件時才會生效

  • 主專案的組態步驟假設外部專案使用 CMake 作為其建置系統。

  • 外部專案的安裝命令實際運行。請注意,由於 ExternalProject 可能在內部使用時間戳記的方式,如果安裝步驟相依的任何內容都不需要重新執行,則安裝命令也可能不需要運行。

另請注意,ExternalProject 不會檢查 CMAKE_INSTALL_MODE 環境變數是否在一次執行與另一次執行之間發生變化。

測試步驟選項

僅在提供以下 TEST_... 選項中的至少一個時,才會定義測試步驟。

TEST_COMMAND <cmd>...

覆寫預設的測試命令(支援 產生器 表達式)。如果未提供此選項,則測試步驟的預設行為是建置外部專案自身的 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

輸出記錄選項

以下每個 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 <bool>

為組態步驟提供終端機的存取權限。

USES_TERMINAL_BUILD <bool>

賦予建置步驟存取終端機的權限。

USES_TERMINAL_INSTALL <bool>

賦予安裝步驟存取終端機的權限。

USES_TERMINAL_TEST <bool>

賦予測試步驟存取終端機的權限。

目標選項

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() 以進一步討論此選項的效果。

雜項選項

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() 來建立的。請參閱該命令的文件,了解某些選項支援的自動取代。

取得專案屬性

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

此自訂步驟要執行的命令列(支援 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 目錄屬性,會指示該函式內部呼叫 ExternalProject_Add_StepTargets(),並針對指定的步驟使用 NO_DEPENDS 選項。

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    git@github.com:FooCo/FooBar.git
  GIT_TAG           origin/release/1.2.3
)

為了方便說明,也定義第二個假設的外部專案,名為 SecretSauce,它是從網頁伺服器下載的。提供兩個網址以便在內部網路速度較快時利用,並在速度較慢的外部伺服器上做為備援。這個專案是一個典型的 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 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