find_package

注意

如需此一般主題的高階介紹,請參閱 使用依賴項指南find_package() 命令在此指南中佔有更全面的位置,包括其與 FetchContent 模組的關係。建議在繼續閱讀以下詳細資訊之前,先閱讀此指南。

尋找套件(通常由專案外部的某物提供),並載入其套件特定的詳細資訊。此命令的呼叫也可以被依賴提供者攔截。

典型用法

大多數對 find_package() 的呼叫通常具有以下形式

find_package(<PackageName> [<version>] [REQUIRED] [COMPONENTS <components>...])

<PackageName> 是唯一強制性的引數。<version> 通常會省略,如果專案在沒有套件的情況下無法成功設定,則應給定 REQUIRED。一些更複雜的套件支援可以使用 COMPONENTS 關鍵字選擇的組件,但大多數套件沒有那麼複雜的程度。

以上是基本簽名的簡化形式。在可能的情況下,專案應使用此形式尋找套件。這降低了複雜性,並最大程度地增加了可以找到或提供套件的方式。

理解基本簽名應足以用於 find_package() 的一般用法。打算提供套件組態檔的專案維護者應理解更大的藍圖,如完整簽名以及此頁面上所有後續章節中所述。

搜尋模式

此命令具有幾種搜尋套件的模式

模組模式

在此模式下,CMake 搜尋名為 Find<PackageName>.cmake 的檔案,首先在 CMAKE_MODULE_PATH 中列出的位置搜尋,然後在 CMake 安裝提供的尋找模組中搜尋。如果找到該檔案,CMake 會讀取並處理它。它負責尋找套件、檢查版本以及產生任何需要的訊息。一些尋找模組對版本控制的支援有限或沒有支援;請檢查尋找模組的文件。

Find<PackageName>.cmake 檔案通常不是由套件本身提供的。相反,它通常是由套件外部的某物提供的,例如作業系統、CMake 本身,甚至是呼叫 find_package() 命令的專案。由於是外部提供的,尋找模組 往往本質上是啟發式的,並且容易過時。它們通常搜尋特定的程式庫、檔案和其他套件構件。

基本命令簽名基本命令簽名僅支援模組模式。

Config 模式

在此模式下,CMake 搜尋名為 <lowercasePackageName>-config.cmake<PackageName>Config.cmake 的檔案。如果指定了版本詳細資訊,它也會尋找 <lowercasePackageName>-config-version.cmake<PackageName>ConfigVersion.cmake(請參閱Config 模式版本選擇,以瞭解如何使用這些獨立的版本檔案)。

注意

如果啟用了實驗性的 CMAKE_EXPERIMENTAL_FIND_CPS_PACKAGES,也會考慮名為 <PackageName>.cps<lowercasePackageName>.cps 的檔案。這些檔案根據通用套件規範 (CPS) 提供套件資訊,這比 CMake 腳本更具可攜性。除了任何明確註明的例外情況外,對「組態檔」、「Config 模式」、「套件組態檔」等的任何引用都同樣適用於 CPS 和 CMake 腳本檔案。此功能仍在開發中,某些功能可能會遺失。

搜尋的實作方式在大多數情況下會傾向於通用套件規範檔案,而不是 CMake 腳本組態檔。指定 CONFIGS 會抑制對 CPS 檔案的考慮。

在 Config 模式中,可以為命令提供要搜尋的名稱清單作為套件名稱。CMake 搜尋組態和版本檔案的位置比模組模式複雜得多(請參閱Config 模式搜尋程序)。

組態和版本檔案通常作為套件的一部分安裝,因此它們比尋找模組更可靠。它們通常包含套件內容的直接知識,因此在組態或版本檔案本身中不需要搜尋或啟發式方法。

基本基本完整命令簽名都支援 Config 模式。

FetchContent 重定向模式

版本 3.24 新增:find_package() 的呼叫可以在內部重定向到 FetchContent 模組提供的套件。對於呼叫者而言,行為看起來會類似於 Config 模式,只是搜尋邏輯被繞過且未使用組件資訊。有關更多詳細資訊,請參閱 FetchContent_Declare()FetchContent_MakeAvailable()

當未重定向到 FetchContent 提供的套件時,命令引數會決定是使用模組模式還是 Config 模式。使用基本簽名時,命令會先在模組模式下搜尋。如果找不到套件,搜尋會回退到 Config 模式。使用者可以將 CMAKE_FIND_PACKAGE_PREFER_CONFIG 變數設定為 true,以反轉優先順序,並指示 CMake 先使用 Config 模式搜尋,然後再回退到模組模式。基本簽名也可以使用 MODULE 關鍵字強制僅使用模組模式。如果使用完整簽名,則命令僅在 Config 模式下搜尋。

基本簽名

find_package(<PackageName> [version] [EXACT] [QUIET] [MODULE]
             [REQUIRED] [[COMPONENTS] [components...]]
             [OPTIONAL_COMPONENTS components...]
             [REGISTRY_VIEW  (64|32|64_32|32_64|HOST|TARGET|BOTH)]
             [GLOBAL]
             [NO_POLICY_SCOPE]
             [BYPASS_PROVIDER])

模組和 Config 模式都支援基本簽名。MODULE 關鍵字表示僅模組模式可用於尋找套件,而不會回退到 Config 模式。

無論使用哪種模式,都會設定 <PackageName>_FOUND 變數,以指示是否找到套件。找到套件後,可以透過套件本身記錄的其他變數和匯入目標提供套件特定的資訊。QUIET 選項會停用資訊性訊息,包括那些指示找不到套件(如果套件不是 REQUIRED 的情況)。如果找不到套件,REQUIRED 選項會停止處理並顯示錯誤訊息。

所需的組件的套件特定清單可以在 COMPONENTS 關鍵字之後列出。如果無法滿足這些組件中的任何一個,則整體套件會被視為找不到。如果 REQUIRED 選項也存在,則這會被視為致命錯誤,否則執行仍會繼續。作為一種簡寫形式,如果 REQUIRED 選項存在,則可以省略 COMPONENTS 關鍵字,並且所需的組件可以直接在 REQUIRED 之後列出。

其他可選組件可以在 OPTIONAL_COMPONENTS 之後列出。如果無法滿足這些組件,只要滿足所有必需的組件,整體套件仍然可以被視為已找到。

可用組件的集合及其含義由目標套件定義

  • 對於 CMake 腳本套件組態檔,正式而言,如何解釋提供給它的組件資訊取決於目標套件,但它應遵循上述預期。對於未指定組件的呼叫,沒有單一預期的行為,目標套件應清楚地定義在這種情況下會發生什麼。常見的安排包括假設它應尋找所有組件、沒有組件或可用組件的某些明確定義的子集。

  • 通用套件規範套件由根組態檔和零個或多個附錄組成,每個附錄都提供組件,並且可能具有依賴項。CMake 始終嘗試載入根組態檔。僅當可以滿足其依賴項,並且它們提供請求的組件,或者未請求任何組件時,才會載入附錄。如果無法滿足提供所需組件的附錄的依賴項,則會將套件視為找不到。否則,將忽略該附錄。

版本 3.24 新增:REGISTRY_VIEW 關鍵字指定應查詢哪個登錄檢視。此關鍵字僅在 Windows 平台上才有意義,在所有其他平台上都將被忽略。正式而言,如何解釋提供給它的登錄檢視資訊取決於目標套件。

版本 3.24 新增:指定 GLOBAL 關鍵字會將所有匯入的目標提升到匯入專案中的全域範圍。或者,可以透過設定 CMAKE_FIND_PACKAGE_TARGETS_GLOBAL 變數來啟用此功能。

[version] 引數請求找到的套件應相容的版本。它可以指定兩種可能的格式

  • 具有 major[.minor[.patch[.tweak]]] 格式的單個版本,其中每個組件都是數值。

  • 具有 versionMin...[<]versionMax 格式的版本範圍,其中 versionMinversionMax 具有相同的格式,並且對組件的約束與單個版本一樣是整數。預設情況下,兩個端點都包含在內。透過指定 <,將排除上限端點。僅 CMake 3.19 或更高版本支援版本範圍。

注意

除了 CPS 套件外,目前僅在每個套件的基礎上提供版本支援。當指定版本範圍,但套件僅設計為預期單個版本時,套件將忽略範圍的上限端點,而僅考慮範圍下限的單個版本。非 CPS 套件以個別套件決定的方式支援版本範圍。請參閱下面的版本選擇章節,以瞭解詳細資訊和重要的注意事項。

EXACT 選項請求版本必須完全匹配。此選項與版本範圍的規格不相容。

如果在尋找模組內的遞迴調用中未給定 [version] 和/或組件清單,則會自動從外部呼叫轉發對應的引數(包括 [version]EXACT 旗標)。

有關 NO_POLICY_SCOPE 選項的討論,請參閱 cmake_policy() 命令文件。

版本 3.24 新增:僅當 find_package()依賴提供者呼叫時,才允許使用 BYPASS_PROVIDER 關鍵字。提供者可以使用它直接呼叫內建的 find_package() 實作,並防止該呼叫重新路由回自身。未來版本的 CMake 可能會偵測到從依賴提供者以外的位置嘗試使用此關鍵字,並以致命錯誤停止。

完整簽名

find_package(<PackageName> [version] [EXACT] [QUIET]
             [REQUIRED] [[COMPONENTS] [components...]]
             [OPTIONAL_COMPONENTS components...]
             [CONFIG|NO_MODULE]
             [GLOBAL]
             [NO_POLICY_SCOPE]
             [BYPASS_PROVIDER]
             [NAMES name1 [name2 ...]]
             [CONFIGS config1 [config2 ...]]
             [HINTS path1 [path2 ...]]
             [PATHS path1 [path2 ...]]
             [REGISTRY_VIEW  (64|32|64_32|32_64|HOST|TARGET|BOTH)]
             [PATH_SUFFIXES suffix1 [suffix2 ...]]
             [NO_DEFAULT_PATH]
             [NO_PACKAGE_ROOT_PATH]
             [NO_CMAKE_PATH]
             [NO_CMAKE_ENVIRONMENT_PATH]
             [NO_SYSTEM_ENVIRONMENT_PATH]
             [NO_CMAKE_PACKAGE_REGISTRY]
             [NO_CMAKE_BUILDS_PATH] # Deprecated; does nothing.
             [NO_CMAKE_SYSTEM_PATH]
             [NO_CMAKE_INSTALL_PREFIX]
             [NO_CMAKE_SYSTEM_PACKAGE_REGISTRY]
             [CMAKE_FIND_ROOT_PATH_BOTH |
              ONLY_CMAKE_FIND_ROOT_PATH |
              NO_CMAKE_FIND_ROOT_PATH])

CONFIG 選項、同義的 NO_MODULE 選項或使用未在基本簽名中指定的選項都會強制執行純 Config 模式。在純 Config 模式下,命令會跳過模組模式搜尋,並立即繼續 Config 模式搜尋。

Config 模式搜尋嘗試尋找要尋找的套件提供的組態檔。建立名為 <PackageName>_DIR 的快取項目,以保留包含該檔案的目錄。預設情況下,命令搜尋名稱為 <PackageName> 的套件。如果給定 NAMES 選項,則使用其後的名稱而不是 <PackageName>。在決定是否將呼叫重定向到 FetchContent 提供的套件時,也會考慮這些名稱。

對於指定的每個名稱,命令都會搜尋名為 <PackageName>Config.cmake<lowercasePackageName>-config.cmake 的檔案。可以使用 CONFIGS 選項給定一組替代的可能組態檔名稱。下面指定了Config 模式搜尋程序。找到後,會檢查任何版本約束,如果滿足,CMake 會讀取並處理組態檔。由於該檔案由套件提供,因此它已經知道套件內容的位置。組態檔的完整路徑儲存在 CMake 變數 <PackageName>_CONFIG 中。

注意

如果啟用了實驗性的 CMAKE_EXPERIMENTAL_FIND_CPS_PACKAGES,除非給定 CONFIGS,否則也會考慮名為 <PackageName>.cps<lowercasePackageName>.cps 的檔案。

CMake 在搜尋具有適當版本的套件時已考慮的所有組態檔都儲存在 <PackageName>_CONSIDERED_CONFIGS 變數中,相關的版本儲存在 <PackageName>_CONSIDERED_VERSIONS 變數中。

如果找不到套件組態檔,除非指定 QUIET 引數,否則 CMake 將產生描述問題的錯誤。如果指定了 REQUIRED 且找不到套件,則會產生致命錯誤,並且組態步驟停止執行。如果 <PackageName>_DIR 已設定為不包含組態檔的目錄,CMake 將忽略它並從頭開始搜尋。

鼓勵提供套件組態檔的套件維護者命名並安裝它們,以便下面概述的Config 模式搜尋程序能夠找到它們,而無需使用其他選項。

Config 模式搜尋程序

注意

使用 Config 模式時,無論給定完整簽名還是基本簽名,都將應用此搜尋程序。

版本 3.24 新增:所有對 find_package() 的呼叫(即使在模組模式下)首先在 CMAKE_FIND_PACKAGE_REDIRECTS_DIR 目錄中尋找 Config 套件檔案。FetchContent 模組,甚至專案本身,都可以將檔案寫入該位置,以將 find_package() 呼叫重定向到專案已提供的內容。如果在該位置找不到 Config 套件檔案,則搜尋將繼續執行下面描述的邏輯。

CMake 構造了一組套件的可能安裝前綴。在每個前綴下,都會搜尋多個目錄以尋找組態檔。下表顯示了搜尋的目錄。每個條目都適用於遵循 Windows (W)、UNIX (U) 或 Apple (A) 慣例的安裝樹

條目

慣例

<prefix>/<name>/cps/ [2]

W

<prefix>/<name>/*/cps/ [2]

W

<prefix>/cps/<name>/ [2]

W

<prefix>/cps/<name>/*/ [2]

W

<prefix>/cps/ [2]

W

<prefix>/

W

<prefix>/(cmake|CMake)/

W

<prefix>/<name>*/

W

<prefix>/<name>*/(cmake|CMake)/

W

<prefix>/<name>*/(cmake|CMake)/<name>*/ [1]

W

<prefix>/(lib/<arch>|lib*|share)/cps/<name>/ [2]

U

<prefix>/(lib/<arch>|lib*|share)/cps/<name>/*/ [2]

U

<prefix>/(lib/<arch>|lib*|share)/cps/ [2]

U

<prefix>/(lib/<arch>|lib*|share)/cmake/<name>*/

U

<prefix>/(lib/<arch>|lib*|share)/<name>*/

U

<prefix>/(lib/<arch>|lib*|share)/<name>*/(cmake|CMake)/

U

<prefix>/<name>*/(lib/<arch>|lib*|share)/cmake/<name>*/

W/U

<prefix>/<name>*/(lib/<arch>|lib*|share)/<name>*/

W/U

<prefix>/<name>*/(lib/<arch>|lib*|share)/<name>*/(cmake|CMake)/

W/U

在支援 macOS FRAMEWORKBUNDLE 的系統上,將在以下目錄中搜尋包含組態檔的 Frameworks 或應用程式套件

條目

慣例

<prefix>/<name>.framework/Versions/*/Resources/CPS/ [3]

A

<prefix>/<name>.framework/Resources/CPS/ [3]

A

<prefix>/<name>.framework/Resources/

A

<prefix>/<name>.framework/Resources/CMake/

A

<prefix>/<name>.framework/Versions/*/Resources/

A

<prefix>/<name>.framework/Versions/*/Resources/CMake/

A

<prefix>/<name>.app/Contents/Resources/CPS/ [3]

A

<prefix>/<name>.app/Contents/Resources/

A

<prefix>/<name>.app/Contents/Resources/CMake/

A

在搜尋上述路徑時,find_package 將僅在包含 /cps/ 的搜尋路徑中尋找 .cps 檔案,否則僅尋找 .cmake 檔案。(這僅適用於指定的路徑,不考慮 <prefix><name> 的內容。)

在所有情況下,<name> 都被視為不區分大小寫,並且對應於指定的任何名稱(<PackageName>NAMES 給定的名稱)。

如果至少啟用了一種編譯語言,則可以根據編譯器的目標架構,按以下順序搜尋特定於架構的 lib/<arch>lib* 目錄

lib/<arch>

如果設定了 CMAKE_LIBRARY_ARCHITECTURE 變數,則進行搜尋。

lib64

在 64 位元平台 (CMAKE_SIZEOF_VOID_P 為 8) 上搜尋,並且 FIND_LIBRARY_USE_LIB64_PATHS 屬性設定為 TRUE

lib32

在 32 位元平台 (CMAKE_SIZEOF_VOID_P 為 4) 上搜尋,並且 FIND_LIBRARY_USE_LIB32_PATHS 屬性設定為 TRUE

libx32

如果 FIND_LIBRARY_USE_LIBX32_PATHS 屬性設定為 TRUE,則在使用 x32 ABI 的平台上搜尋。

lib

總是搜尋。

版本 3.24 變更:Windows 平台上,可以使用專用語法將登錄查詢包含為透過 HINTSPATHS 關鍵字指定的目錄的一部分。此類規格將在所有其他平台上被忽略。

版本 3.24 新增:可以指定 REGISTRY_VIEW 來管理指定為 PATHSHINTS 一部分的 Windows 登錄查詢。

指定必須查詢的登錄檢視。此選項僅在 Windows 平台上才有意義,在其他平台上會被忽略。若未指定,當 CMP0134 政策為 NEW 時,會使用 TARGET 檢視。當政策為 OLD 時的預設檢視,請參閱 CMP0134

64

查詢 64 位元登錄檔。在 32 位元 Windows 上,它總是回傳字串 /REGISTRY-NOTFOUND

32

查詢 32 位元登錄檔。

64_32

查詢兩個檢視(6432)並為每個檢視產生一個路徑。

32_64

查詢兩個檢視(3264)並為每個檢視產生一個路徑。

HOST

查詢與主機架構相符的登錄檔:在 64 位元 Windows 上為 64,在 32 位元 Windows 上為 32

TARGET

查詢與 CMAKE_SIZEOF_VOID_P 變數指定的架構相符的登錄檔。若未定義,則回退到 HOST 檢視。

BOTH

查詢兩個檢視(3264)。順序取決於以下規則:如果定義了 CMAKE_SIZEOF_VOID_P 變數,則根據此變數的內容使用以下檢視

  • 8: 64_32

  • 4: 32_64

如果未定義 CMAKE_SIZEOF_VOID_P 變數,則依賴主機的架構

  • 64 位元:64_32

  • 32 位元:32

如果指定了 PATH_SUFFIXES,則後綴會逐一附加到每個 (W) 或 (U) 目錄條目。

這組目錄旨在與在其安裝樹中提供組態檔的專案協同工作。標記為 (W) 的目錄適用於 Windows 上的安裝,其中前綴可能指向應用程式安裝目錄的頂層。標記為 (U) 的目錄適用於 UNIX 平台上的安裝,其中前綴由多個套件共用。這僅僅是一種慣例,因此所有 (W) 和 (U) 目錄仍然會在所有平台上搜尋。標記為 (A) 的目錄適用於 Apple 平台上的安裝。CMAKE_FIND_FRAMEWORKCMAKE_FIND_APPBUNDLE 變數決定了偏好順序。

警告

CMAKE_FIND_FRAMEWORKCMAKE_FIND_APPBUNDLE 設定為 FIRST(預設值)以外的值,將導致 CMake 以不同於規格中設定的順序搜尋通用套件規格檔案。

安裝前綴的集合是使用以下步驟建構的。如果指定了 NO_DEFAULT_PATH,則會啟用所有 NO_* 選項。

  1. 搜尋目前正在尋找的 <PackageName> 獨有的前綴。請參閱政策 CMP0074

    在版本 3.12 中新增。

    具體而言,依序搜尋以下變數指定的前綴

    1. <PackageName>_ROOT CMake 變數,其中 <PackageName> 是大小寫保留的套件名稱。

    2. <PACKAGENAME>_ROOT CMake 變數,其中 <PACKAGENAME> 是大寫的套件名稱。請參閱政策 CMP0144

      在版本 3.27 中新增。

    3. <PackageName>_ROOT 環境變數,其中 <PackageName> 是大小寫保留的套件名稱。

    4. <PACKAGENAME>_ROOT 環境變數,其中 <PACKAGENAME> 是大寫的套件名稱。請參閱政策 CMP0144

      在版本 3.27 中新增。

    套件根變數維護為堆疊,因此如果從尋找模組內部呼叫,則也會在目前套件的路徑之後搜尋父尋找模組的根路徑。如果傳遞 NO_PACKAGE_ROOT_PATH 或將 CMAKE_FIND_USE_PACKAGE_ROOT_PATH 設定為 FALSE,則可以跳過此步驟。

  2. 在 CMake 特定快取變數中指定的搜尋路徑。這些旨在與 -DVAR=VALUE 命令列一起使用。這些值被解釋為以分號分隔的列表。如果傳遞 NO_CMAKE_PATH 或將 CMAKE_FIND_USE_CMAKE_PATH 設定為 FALSE,則可以跳過此步驟

  3. 在 CMake 特定環境變數中指定的搜尋路徑。這些旨在在使用者的 shell 組態中設定,因此使用主機的原生路徑分隔符號(Windows 上為 ;,UNIX 上為 :)。如果傳遞 NO_CMAKE_ENVIRONMENT_PATH 或將 CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH 設定為 FALSE,則可以跳過此步驟

  4. HINTS 選項指定的搜尋路徑。這些應該是由系統自檢計算的路徑,例如已找到的另一個項目位置提供的提示。硬編碼的猜測應使用 PATHS 選項指定。

  5. 搜尋標準系統環境變數。如果傳遞 NO_SYSTEM_ENVIRONMENT_PATH 或將 CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH 設定為 FALSE,則可以跳過此步驟。以 /bin/sbin 結尾的路徑條目會自動轉換為其父目錄

    • PATH

  6. 搜尋儲存在 CMake 使用者套件登錄檔 中的路徑。如果傳遞 NO_CMAKE_PACKAGE_REGISTRY 或將變數 CMAKE_FIND_USE_PACKAGE_REGISTRY 設定為 FALSE 或將已棄用的變數 CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY 設定為 TRUE,則可以跳過此步驟。

    有關使用者套件登錄檔的詳細資訊,請參閱 cmake-packages(7) 手冊。

  7. 搜尋在目前系統的平台檔案中定義的 CMake 變數。如果傳遞 NO_CMAKE_INSTALL_PREFIX 或將 CMAKE_FIND_USE_INSTALL_PREFIX 設定為 FALSE,則可以跳過對 CMAKE_INSTALL_PREFIXCMAKE_STAGING_PREFIX 的搜尋。如果傳遞 NO_CMAKE_SYSTEM_PATH 或將 CMAKE_FIND_USE_CMAKE_SYSTEM_PATH 設定為 FALSE,則可以跳過所有這些位置

    這些變數包含的平台路徑是通常包含已安裝軟體的位置。例如,UNIX 平台上的 /usr/local

  8. 搜尋儲存在 CMake 系統套件登錄檔 中的路徑。如果傳遞 NO_CMAKE_SYSTEM_PACKAGE_REGISTRY 或將 CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY 變數設定為 FALSE 或將已棄用的變數 CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY 設定為 TRUE,則可以跳過此步驟。

    有關系統套件登錄檔的詳細資訊,請參閱 cmake-packages(7) 手冊。

  9. PATHS 選項指定的搜尋路徑。這些通常是硬編碼的猜測。

CMAKE_IGNORE_PATHCMAKE_IGNORE_PREFIX_PATHCMAKE_SYSTEM_IGNORE_PATHCMAKE_SYSTEM_IGNORE_PREFIX_PATH 變數也可能導致忽略上述某些位置。

路徑會按照上述順序搜尋。找到的第一個可行的套件組態檔會被使用,即使更新版本的套件位於搜尋路徑列表的後面。

對於包含 glob 表達式 (*) 的搜尋路徑,除非設定了 CMAKE_FIND_PACKAGE_SORT_ORDER 變數,否則搜尋符合 glob 的目錄的順序是未指定的。此變數以及 CMAKE_FIND_PACKAGE_SORT_DIRECTION 變數,決定了 CMake 考量 glob 比對的順序。例如,如果檔案系統包含套件組態檔

<prefix>/example-1.2/example-config.cmake
<prefix>/example-1.10/example-config.cmake
<prefix>/share/example-2.0/example-config.cmake

則當上述變數未設定時,find_package(example) 將找到 example-1.2 還是 example-1.10(假設兩者都可行)是未指定的,但 find_package 將*不會*找到 example-2.0,因為其中另一個將首先被找到。

若要控制 find_package 搜尋符合 glob 表達式的目錄的順序,請使用 CMAKE_FIND_PACKAGE_SORT_ORDERCMAKE_FIND_PACKAGE_SORT_DIRECTION。例如,若要使上述範例選擇 example-1.10,可以設定

set(CMAKE_FIND_PACKAGE_SORT_ORDER NATURAL)
set(CMAKE_FIND_PACKAGE_SORT_DIRECTION DEC)

在呼叫 find_package 之前。

在版本 3.16 中新增:新增了 CMAKE_FIND_USE_<CATEGORY> 變數,以全域停用各種搜尋位置。

在版本 4.0 中變更:變數 CMAKE_FIND_PACKAGE_SORT_ORDERCMAKE_FIND_PACKAGE_SORT_DIRECTION 現在也控制 find_package 在搜尋路徑 <prefix>/<name>.framework/Versions/*/Resources/<prefix>/<name>.framework/Versions/*/Resources/CMake 中搜尋符合 glob 表達式的目錄的順序。在先前的 CMake 版本中,此順序是未指定的。

CMake 變數 CMAKE_FIND_ROOT_PATH 指定一個或多個要前置到所有其他搜尋目錄的目錄。這有效地將整個搜尋「重新植根」到給定的位置下。屬於 CMAKE_STAGING_PREFIX 後代的路徑會從此重新植根中排除,因為該變數始終是主機系統上的路徑。預設情況下,CMAKE_FIND_ROOT_PATH 為空。

CMAKE_SYSROOT 變數也可用於指定恰好一個目錄作為前綴。設定 CMAKE_SYSROOT 也具有其他效果。有關更多資訊,請參閱該變數的文件。

這些變數在交叉編譯時特別有用,可指向目標環境的根目錄,CMake 也會在該處搜尋。預設情況下,首先搜尋 CMAKE_FIND_ROOT_PATH 中列出的目錄,然後搜尋 CMAKE_SYSROOT 目錄,然後搜尋未植根的目錄。可以透過設定 CMAKE_FIND_ROOT_PATH_MODE_PACKAGE 來調整預設行為。可以使用選項在每次呼叫時手動覆寫此行為

CMAKE_FIND_ROOT_PATH_BOTH

按照上述順序搜尋。

NO_CMAKE_FIND_ROOT_PATH

不使用 CMAKE_FIND_ROOT_PATH 變數。

ONLY_CMAKE_FIND_ROOT_PATH

僅搜尋重新植根的目錄和 CMAKE_STAGING_PREFIX 下方的目錄。

預設搜尋順序旨在對於常見用例而言,從最特定到最不特定。專案可以透過簡單地多次呼叫命令並使用 NO_* 選項來覆寫順序

find_package (<PackageName> PATHS paths... NO_DEFAULT_PATH)
find_package (<PackageName>)

一旦其中一個呼叫成功,結果變數將被設定並儲存在快取中,以便沒有呼叫會再次搜尋。

預設情況下,儲存在結果變數中的值將是找到檔案的路徑。可以在呼叫 find_package 之前將 CMAKE_FIND_PACKAGE_RESOLVE_SYMLINKS 變數設定為 TRUE,以便解析符號連結並儲存檔案的真實路徑。

每個非 REQUIRED 的 find_package 呼叫都可以停用或設為 REQUIRED

同時將兩個變數都設定為 TRUE 是錯誤的。

組態模式版本選擇

注意

當使用組態模式時,無論給定的是完整簽名還是基本簽名,都會套用此版本選擇過程。

當給定 [version] 引數時,組態模式將僅尋找聲稱與請求的版本相容的套件版本(請參閱 格式規格)。如果給定 EXACT 選項,則只能找到聲稱與請求的版本完全匹配的套件版本。CMake 沒有建立任何版本號含義的慣例。

CMake 腳本

對於 CMake 腳本套件組態檔,套件版本號碼由套件本身提供的「版本」檔案或由 FetchContent 檢查。對於候選套件組態檔 <config-file>.cmake,對應的版本檔案位於其旁邊,並命名為 <config-file>-version.cmake<config-file>Version.cmake。如果沒有此類版本檔案可用,則假定組態檔與任何請求的版本都不相容。可以使用 CMakePackageConfigHelpers 模組建立包含通用版本比對程式碼的基本版本檔案。找到版本檔案後,會載入該檔案以檢查請求的版本號碼。版本檔案會在巢狀範圍中載入,其中已定義以下變數

PACKAGE_FIND_NAME

<PackageName>

PACKAGE_FIND_VERSION

完整的請求版本字串

PACKAGE_FIND_VERSION_MAJOR

如果請求,則為主要版本;否則為 0

PACKAGE_FIND_VERSION_MINOR

如果請求,則為次要版本;否則為 0

PACKAGE_FIND_VERSION_PATCH

如果請求,則為修補版本;否則為 0

PACKAGE_FIND_VERSION_TWEAK

如果請求,則為微調版本;否則為 0

PACKAGE_FIND_VERSION_COUNT

版本組件的數量,0 到 4

當指定版本範圍時,上述版本變數將根據版本範圍的下限來保存值。這是為了保持與尚未實作以預期版本範圍的套件的相容性。此外,版本範圍將由以下變數描述

PACKAGE_FIND_VERSION_RANGE

完整請求的版本範圍字串

PACKAGE_FIND_VERSION_RANGE_MIN

這指定版本範圍的下限端點是否應包含或排除。目前,此變數唯一支援的值為 INCLUDE

PACKAGE_FIND_VERSION_RANGE_MAX

這指定版本範圍的上限端點是否應包含或排除。此變數支援的值為 INCLUDEEXCLUDE

PACKAGE_FIND_VERSION_MIN

範圍下限端點的完整請求版本字串

PACKAGE_FIND_VERSION_MIN_MAJOR

請求時範圍下限端點的主要版本,否則為 0

PACKAGE_FIND_VERSION_MIN_MINOR

請求時範圍下限端點的次要版本,否則為 0

PACKAGE_FIND_VERSION_MIN_PATCH

請求時範圍下限端點的修補版本,否則為 0

PACKAGE_FIND_VERSION_MIN_TWEAK

請求時範圍下限端點的微調版本,否則為 0

PACKAGE_FIND_VERSION_MIN_COUNT

範圍下限端點的版本組件數量,0 到 4

PACKAGE_FIND_VERSION_MAX

範圍上限端點的完整請求版本字串

PACKAGE_FIND_VERSION_MAX_MAJOR

請求時範圍上限端點的主要版本,否則為 0

PACKAGE_FIND_VERSION_MAX_MINOR

請求時範圍上限端點的次要版本,否則為 0

PACKAGE_FIND_VERSION_MAX_PATCH

請求時範圍上限端點的修補版本,否則為 0

PACKAGE_FIND_VERSION_MAX_TWEAK

請求時範圍上限端點的微調版本,否則為 0

PACKAGE_FIND_VERSION_MAX_COUNT

範圍上限端點的版本組件數量,0 到 4

無論指定單一版本或版本範圍,變數 PACKAGE_FIND_VERSION_COMPLETE 都將被定義,並將保存完整的請求版本字串,如指定的那樣。

版本檔案會檢查它是否滿足請求的版本並設定這些變數

PACKAGE_VERSION

完整提供的版本字串

PACKAGE_VERSION_EXACT

如果版本完全符合則為 True

PACKAGE_VERSION_COMPATIBLE

如果版本相容則為 True

PACKAGE_VERSION_UNSUITABLE

如果版本不適合作為任何版本則為 True

這些變數由 find_package 命令檢查,以確定組態檔是否提供可接受的版本。它們在 find_package 呼叫返回後不可用。如果版本可接受,則會設定以下變數

<PackageName>_VERSION

完整提供的版本字串

<PackageName>_VERSION_MAJOR

如果提供主要版本,否則為 0

<PackageName>_VERSION_MINOR

如果提供次要版本,否則為 0

<PackageName>_VERSION_PATCH

如果提供修補版本,否則為 0

<PackageName>_VERSION_TWEAK

如果提供微調版本,否則為 0

<PackageName>_VERSION_COUNT

版本組件的數量,0 到 4

並載入對應的套件組態檔。

注意

雖然版本比對的確切行為由個別套件決定,但許多套件使用 write_basic_package_version_file() 來提供此邏輯。此命令產生的版本檢查腳本在版本範圍方面有一些值得注意的注意事項

  • 版本範圍的上限作為將接受哪些版本的硬性限制。因此,雖然版本要求 1.4.0 可能會被版本為 1.6.0 且聲稱「相同主要版本」相容性的套件滿足,但如果請求的版本範圍為 1.4.0...1.5.0,則同一個套件將被拒絕。

  • 版本範圍的兩端都必須符合套件聲稱的相容性等級。例如,如果一個套件聲稱「相同主要版本和次要版本」相容性,則請求版本範圍 1.4.0...<1.5.51.4.0...1.5.0 將導致該套件被拒絕,即使套件版本為 1.4.1

因此,無法使用版本範圍來擴展將被接受的相容套件版本的範圍。

通用套件規格

對於通用套件規格套件組態檔,套件版本號碼由 CMake 根據一組已識別的版本模式進行檢查。目前,以下模式已被識別

simple

版本號碼是由整數組成的元組,後跟一個可選的尾隨段,該尾隨段在版本比較方面被忽略。

custom

解譯版本號碼的機制未指定。版本字串必須完全匹配才能接受套件。

請參閱 version_schema 以獲得每個模式的更詳細說明以及如何執行每個模式的比較。請注意,該規格可能包含 CMake 不支援的模式。

除了套件的 version 之外,CPS 還允許套件選擇性地指定 compat_version,這是套件提供相容性的最舊版本。也就是說,套件保證期望 compat_version 的消費者應該能夠使用該套件,即使套件的實際版本更新。如果未指定,則 compat_version 隱含地等於套件版本,即不提供向後相容性。

當套件使用已識別的模式時,CMake 將根據以下規則確定套件的可接受性

  • 如果指定了 EXACT,或者如果套件未提供 compat_version,則套件的 version 必須等於請求的版本。

  • 否則

    • 套件的 version 必須大於或等於請求的(最小)版本,且

    • 套件的 compat_version 必須小於或等於請求的(最小)版本,且

    • 如果給定了請求的最大版本,則它必須大於(或等於,取決於最大版本是指定為包含還是排除)套件的 version

注意

選擇此範圍比對的實作是為了最接近地匹配 write_basic_package_version_file() 的行為,儘管沒有過於寬泛的範圍與任何內容都不匹配的情況。

對於使用 simple 版本模式的套件,如果版本可接受,則會設定以下變數

<PackageName>_VERSION

完整提供的版本字串

<PackageName>_VERSION_MAJOR

如果提供主要版本,否則為 0

<PackageName>_VERSION_MINOR

如果提供次要版本,否則為 0

<PackageName>_VERSION_PATCH

如果提供修補版本,否則為 0

<PackageName>_VERSION_TWEAK

如果提供微調版本,否則為 0

<PackageName>_VERSION_COUNT

版本組件數量,非負數

套件檔案介面變數

當載入尋找模組或 CMake 腳本套件組態檔時,find_package 定義變數以提供有關呼叫引數的資訊(並在返回之前還原其原始狀態)

CMAKE_FIND_PACKAGE_NAME

正在搜尋的 <PackageName>

<PackageName>_FIND_REQUIRED

如果給定了 REQUIRED 選項則為 True

<PackageName>_FIND_QUIETLY

如果給定了 QUIET 選項則為 True

<PackageName>_FIND_REGISTRY_VIEW

如果給定了 REGISTRY_VIEW 選項則為請求的檢視

<PackageName>_FIND_VERSION

完整的請求版本字串

<PackageName>_FIND_VERSION_MAJOR

如果請求,則為主要版本;否則為 0

<PackageName>_FIND_VERSION_MINOR

如果請求,則為次要版本;否則為 0

<PackageName>_FIND_VERSION_PATCH

如果請求,則為修補版本;否則為 0

<PackageName>_FIND_VERSION_TWEAK

如果請求,則為微調版本;否則為 0

<PackageName>_FIND_VERSION_COUNT

版本組件的數量,0 到 4

<PackageName>_FIND_VERSION_EXACT

如果給定了 EXACT 選項則為 True

<PackageName>_FIND_COMPONENTS

指定的組件清單(必要和可選)

<PackageName>_FIND_REQUIRED_<c>

如果組件 <c> 是必要的則為 True,如果組件 <c> 是可選的則為 false

當指定版本範圍時,上述版本變數將根據版本範圍的下限來保存值。這是為了保持與尚未實作以預期版本範圍的套件的相容性。此外,版本範圍將由以下變數描述

<PackageName>_FIND_VERSION_RANGE

完整請求的版本範圍字串

<PackageName>_FIND_VERSION_RANGE_MIN

這指定版本範圍的下限端點是包含還是排除。目前,INCLUDE 是唯一支援的值。

<PackageName>_FIND_VERSION_RANGE_MAX

這指定版本範圍的上限端點是包含還是排除。此變數的可能值為 INCLUDEEXCLUDE

<PackageName>_FIND_VERSION_MIN

範圍下限端點的完整請求版本字串

<PackageName>_FIND_VERSION_MIN_MAJOR

請求時範圍下限端點的主要版本,否則為 0

<PackageName>_FIND_VERSION_MIN_MINOR

請求時範圍下限端點的次要版本,否則為 0

<PackageName>_FIND_VERSION_MIN_PATCH

請求時範圍下限端點的修補版本,否則為 0

<PackageName>_FIND_VERSION_MIN_TWEAK

請求時範圍下限端點的微調版本,否則為 0

<PackageName>_FIND_VERSION_MIN_COUNT

範圍下限端點的版本組件數量,0 到 4

<PackageName>_FIND_VERSION_MAX

範圍上限端點的完整請求版本字串

<PackageName>_FIND_VERSION_MAX_MAJOR

請求時範圍上限端點的主要版本,否則為 0

<PackageName>_FIND_VERSION_MAX_MINOR

請求時範圍上限端點的次要版本,否則為 0

<PackageName>_FIND_VERSION_MAX_PATCH

請求時範圍上限端點的修補版本,否則為 0

<PackageName>_FIND_VERSION_MAX_TWEAK

請求時範圍上限端點的微調版本,否則為 0

<PackageName>_FIND_VERSION_MAX_COUNT

範圍上限端點的版本組件數量,0 到 4

無論指定單一版本或版本範圍,變數 <PackageName>_FIND_VERSION_COMPLETE 都將被定義,並將保存完整的請求版本字串,如指定的那樣。

在模組模式下,載入的尋找模組負責遵守這些變數詳述的請求;請參閱尋找模組以了解詳細資訊。在組態模式下,find_package 會自動處理 REQUIREDQUIET[version] 選項,但將組件的處理留給套件組態檔,以符合套件的意義。套件組態檔可能會將 <PackageName>_FOUND 設定為 false,以告知 find_package 組件需求未滿足。

CPS 遞移需求

通用套件規格套件描述由一個或多個組件組成,這些組件可能又依賴於套件內部或外部的其他組件。當需要外部組件時,提供套件會被註記為套件的套件級需求。此外,通常在所述外部套件需求中註記所需的組件集。

在 CMake 腳本套件描述將使用 find_dependency() 命令來處理遞移依賴項的情況下,CMake 使用內部巢狀 find_package 呼叫來自行處理 CPS 的遞移依賴項。此呼叫可以透過另一個 CPS 套件或透過 CMake 腳本套件來解析 CPS 套件依賴項。CPS 組件依賴項的處理方式受到一些注意事項的約束。

當解析遞移依賴項的候選者是另一個 CPS 套件時,事情很簡單;COMPONENTS 和 CPS「組件」可以直接比較(並且實際上與 CMake「匯入目標」同義)。然而,鼓勵 CMake 腳本套件(並且經常這樣做)檢查是否找到所需的組件,無論套件是否描述了單獨的組件。此外,即使是那些描述組件的套件,通常也不像 CPS 那樣與匯入目標具有相同的關聯性。因此,將消耗 CPS 套件宣告的所需組件集傳遞給 COMPONENTS 將導致解析依賴項時出現虛假失敗。

為了處理這個問題,如果解析 CPS 遞移依賴項的候選者是 CMake 腳本套件,CMake 會將消耗 CPS 套件宣告的所需組件作為 OPTIONAL_COMPONENTS 傳遞,並執行單獨的內部檢查,以確認候選套件提供了所需的匯入目標。這些目標的名稱必須為 <PackageName>::<ComponentName>,符合 CPS 慣例,否則檢查將認為找不到該套件。