CMakePackageConfigHelpers

用於建立組態檔的輔助函式,這些組態檔可被其他專案包含,以尋找和使用套件。

產生套件組態檔

configure_package_config_file

為專案建立組態檔

configure_package_config_file(<input> <output>
  INSTALL_DESTINATION <path>
  [PATH_VARS <var1> <var2> ... <varN>]
  [NO_SET_AND_CHECK_MACRO]
  [NO_CHECK_REQUIRED_COMPONENTS_MACRO]
  [INSTALL_PREFIX <path>]
  )

configure_package_config_file() 應取代普通的 configure_file() 命令,當為安裝專案或函式庫建立 <PackageName>Config.cmake<PackageName>-config.cmake 檔案時。 它有助於使產生的套件可重新定位,方法是避免在已安裝的 <PackageName>Config.cmake 檔案中硬編碼路徑。

FooConfig.cmake 檔案中,可能有如下程式碼,使使用中的專案知道安裝目的地

set(FOO_INCLUDE_DIR   "@CMAKE_INSTALL_FULL_INCLUDEDIR@" )
set(FOO_DATA_DIR   "@CMAKE_INSTALL_PREFIX@/@RELATIVE_DATA_INSTALL_DIR@" )
set(FOO_ICONS_DIR   "@CMAKE_INSTALL_PREFIX@/share/icons" )
#...logic to determine installedPrefix from the own location...
set(FOO_CONFIG_DIR  "${installedPrefix}/@CONFIG_INSTALL_DIR@" )

上面顯示的所有四個選項都不夠充分。前三個硬編碼了絕對目錄位置。第四種情況僅在確定 installedPrefix 的邏輯正確,並且 CONFIG_INSTALL_DIR 包含相對路徑時才有效,這通常無法保證。 這會導致產生的 FooConfig.cmake 檔案在 Windows 和 macOS 下運作不佳,在這些系統中,使用者習慣在安裝時選擇二進位套件的安裝位置,而與在建置/cmake 時設定的 CMAKE_INSTALL_PREFIX 無關。

使用 configure_package_config_file() 有所幫助。如果正確使用,它會使產生的 FooConfig.cmake 檔案可重新定位。 用法

  1. 像平常一樣編寫 FooConfig.cmake.in 檔案。

  2. 在頂部插入一行,僅包含字串 @PACKAGE_INIT@

  3. 不要使用 set(FOO_DIR "@SOME_INSTALL_DIR@"),而是使用 set(FOO_DIR "@PACKAGE_SOME_INSTALL_DIR@") (這必須在 @PACKAGE_INIT@ 行之後)。

  4. 不要使用普通的 configure_file() 命令,而是使用 configure_package_config_file()

<input><output> 引數是輸入和輸出檔案,與 configure_file() 中的方式相同。

給定 INSTALL_DESTINATION<path> 必須是 FooConfig.cmake 檔案將安裝到的目的地。此路徑可以是絕對路徑,也可以是相對於 INSTALL_PREFIX 路徑的相對路徑。

作為 PATH_VARS 給定的變數 <var1><varN> 是包含安裝目的地的變數。 對於它們中的每一個,巨集將建立一個輔助變數 PACKAGE_<var...>。 這些輔助變數必須在 FooConfig.cmake.in 檔案中使用,以設定已安裝的位置。 它們由 configure_package_config_file() 計算,以便它們始終相對於套件的已安裝位置。 這對於相對位置和絕對位置都有效。 對於絕對位置,僅當絕對位置是 INSTALL_PREFIX 的子目錄時才有效。

在 3.30 版本中新增: 變數 PACKAGE_PREFIX_DIR 將始終在 @PACKAGE_INIT@ 行之後定義。 它將保留基本安裝位置的值。 一般來說,應該使用透過 PATH_VARS 機制定義的變數,但 PACKAGE_PREFIX_DIR 可用於那些不容易由 PATH_VARS 處理的情況,例如直接安裝到基本安裝位置而不是其子目錄的文件。

注意

當產生檔案的使用者使用 CMake 3.29 或更舊版本時,PACKAGE_PREFIX_DIR 的值可以透過呼叫 find_dependency()find_package() 來變更。 如果專案依賴 PACKAGE_PREFIX_DIR,則專案有責任確保 PACKAGE_PREFIX_DIR 的值在任何此類呼叫或任何其他可能包含由 configure_package_config_file() 產生的另一個檔案的呼叫中保持不變。

在 3.1 版本中新增: 如果傳遞了 INSTALL_PREFIX 引數,則將其用作計算所有相對路徑的基本路徑。 <path> 引數必須是絕對路徑。 如果未傳遞此引數,則將改為使用 CMAKE_INSTALL_PREFIX 變數。 當產生 FooConfig.cmake 檔案以從安裝樹狀結構使用您的套件時,預設值是好的。 當產生 FooConfig.cmake 檔案以從建置樹狀結構使用您的套件時,應使用此選項。

預設情況下,configure_package_config_file() 還會在 FooConfig.cmake 檔案中產生兩個輔助巨集,set_and_check()check_required_components()

set_and_check() 應取代普通的 set() 命令,用於設定目錄和檔案位置。 除了設定變數外,它還檢查引用的檔案或目錄是否實際存在,如果不存在,則會產生致命錯誤。 這確保了產生的 FooConfig.cmake 檔案不包含錯誤的參考。 新增 NO_SET_AND_CHECK_MACRO 選項以防止在 FooConfig.cmake 檔案中產生 set_and_check() 巨集。

check_required_components(<PackageName>) 應在 FooConfig.cmake 檔案的末尾呼叫。 此巨集檢查是否已找到所有請求的非可選組件,如果不是這種情況,它會將 Foo_FOUND 變數設定為 FALSE,以便將套件視為未找到。 它透過測試所有請求的必要組件的 Foo_<Component>_FOUND 變數來做到這一點。 即使套件未提供任何組件,也應呼叫此巨集,以確保使用者不會錯誤地指定組件。 新增 NO_CHECK_REQUIRED_COMPONENTS_MACRO 選項以防止在 FooConfig.cmake 檔案中產生 check_required_components() 巨集。

另請參閱 範例產生套件檔案

產生套件版本檔案

write_basic_package_version_file

為專案建立版本檔案

write_basic_package_version_file(<filename>
  [VERSION <major.minor.patch>]
  COMPATIBILITY <AnyNewerVersion|SameMajorVersion|SameMinorVersion|ExactVersion>
  [ARCH_INDEPENDENT] )

將檔案寫入為用作 <PackageName>ConfigVersion.cmake 檔案到 <filename>。 有關此類檔案的詳細資訊,請參閱 find_package() 的文件。

<filename> 是輸出檔案名,應位於建置樹狀結構中。 <major.minor.patch> 是要安裝的專案的版本號。

如果未給定 VERSION,則使用 PROJECT_VERSION 變數。 如果尚未設定,則會發生錯誤。

COMPATIBILITY 模式 AnyNewerVersion 表示,如果已安裝的套件版本比請求的版本更新或完全相同,則將被視為相容。 此模式應用於完全向後相容的套件,也包括跨主要版本的套件。 如果改用 SameMajorVersion,則行為與 AnyNewerVersion 不同,因為主要版本號必須與請求的版本相同,例如,如果請求的版本為 1.0,則版本 2.0 將不被視為相容。 此模式應用於保證在同一主要版本中向後相容的套件。 如果使用 SameMinorVersion,則行為與 SameMajorVersion 相同,但主要版本和次要版本都必須與請求的版本相同,例如,如果請求的版本為 0.1,則版本 0.2 將不相容。 如果使用 ExactVersion,則僅當請求的版本與其自身的版本號完全匹配時(不考慮微調版本),套件才被視為相容。 例如,套件的版本 1.2.3 僅被視為與請求的版本 1.2.3 相容。 此模式適用於沒有相容性保證的套件。 如果您的專案有更精細的版本匹配規則,您將需要編寫自己的自訂 <PackageName>ConfigVersion.cmake 檔案,而不是使用此巨集。

在 3.11 版本中新增: SameMinorVersion 相容性模式。

在 3.14 版本中新增: 如果給定 ARCH_INDEPENDENT,即使安裝的套件版本是為與請求的架構不同的架構建置的,也將被視為相容。 否則,將執行架構檢查,並且僅當架構完全匹配時,套件才被視為相容。 例如,如果套件是為 32 位架構建置的,則僅當在 32 位架構上使用時,套件才被視為相容,除非給定 ARCH_INDEPENDENT,在這種情況下,套件在任何架構上都被視為相容。

注意

ARCH_INDEPENDENT 適用於僅標頭檔的函式庫或類似的沒有二進位檔的套件。

在 3.19 版本中新增: AnyNewerVersionSameMajorVersionSameMinorVersion 引數的 COMPATIBILITY 產生的版本檔案處理版本範圍(如果指定了版本範圍)(請參閱 find_package() 命令以取得詳細資訊)。 ExactVersion 模式與版本範圍不相容,如果指定了版本範圍,將顯示作者警告。

在內部,此巨集執行 configure_file() 以建立產生的版本檔案。 根據 COMPATIBILITY,使用對應的 BasicConfigVersion-<COMPATIBILITY>.cmake.in 檔案。 請注意,這些檔案是 CMake 的內部檔案,您不應自行在它們上呼叫 configure_file(),但它們可以用作起點,以建立更複雜的自訂 <PackageName>ConfigVersion.cmake 檔案。

產生 Apple 平台選擇檔案

generate_apple_platform_selection_file

在 3.29 版本中新增。

建立 Apple 平台選擇檔案

generate_apple_platform_selection_file(<filename>
  INSTALL_DESTINATION <path>
  [INSTALL_PREFIX <path>]
  [MACOS_INCLUDE_FILE <file>]
  [IOS_INCLUDE_FILE <file>]
  [IOS_SIMULATOR_INCLUDE_FILE <file>]
  [IOS_CATALYST_INCLUDE_FILE <file>]
  [TVOS_INCLUDE_FILE <file>]
  [TVOS_SIMULATOR_INCLUDE_FILE <file>]
  [WATCHOS_INCLUDE_FILE <file>]
  [WATCHOS_SIMULATOR_INCLUDE_FILE <file>]
  [VISIONOS_INCLUDE_FILE <file>]
  [VISIONOS_SIMULATOR_INCLUDE_FILE <file>]
  [ERROR_VARIABLE <variable>]
  )

寫入一個檔案,其中包含特定於 Apple 平台的 .cmake 檔案,例如,用作 <PackageName>Config.cmake。 這可以與 export(SETUP)XCFRAMEWORK_LOCATION 引數結合使用,以導出套件,以便為任何 Apple 平台建置的專案都可以使用它們。

INSTALL_DESTINATION <path>

呼叫端將產生的檔案安裝到的路徑,例如,透過 install(FILES)。 路徑可以是相對於 INSTALL_PREFIX 的相對路徑,也可以是絕對路徑。

INSTALL_PREFIX <path>

呼叫端將套件安裝到的路徑前綴。 <path> 引數必須是絕對路徑。 如果未傳遞此引數,則將改為使用 CMAKE_INSTALL_PREFIX 變數。

MACOS_INCLUDE_FILE <file>

如果平台是 macOS,則包含的檔案。

IOS_INCLUDE_FILE <file>

如果平台是 iOS,則包含的檔案。

IOS_SIMULATOR_INCLUDE_FILE <file>

如果平台是 iOS 模擬器,則包含的檔案。

IOS_CATALYST_INCLUDE_FILE <file>

在 3.31 版本中新增。

如果平台是 iOS Catalyst,則包含的檔案。

TVOS_INCLUDE_FILE <file>

如果平台是 tvOS,則包含的檔案。

TVOS_SIMULATOR_INCLUDE_FILE <file>

如果平台是 tvOS 模擬器,則包含的檔案。

WATCHOS_INCLUDE_FILE <file>

如果平台是 watchOS,則包含的檔案。

WATCHOS_SIMULATOR_INCLUDE_FILE <file>

如果平台是 watchOS 模擬器,則包含的檔案。

VISIONOS_INCLUDE_FILE <file>

如果平台是 visionOS,則包含的檔案。

VISIONOS_SIMULATOR_INCLUDE_FILE <file>

如果平台是 visionOS 模擬器,則包含的檔案。

ERROR_VARIABLE <variable>

如果使用中的專案是為不受支援的平台建置的,則將 <variable> 設定為錯誤訊息。 包含器可以使用此資訊來假裝未找到套件。 如果未給定此選項,則預設行為是發出致命錯誤。

如果未指定任何可選的包含檔案,並且使用中的專案是為其對應的平台建置的,則產生的檔案將認為該平台不受支援。 行為由 ERROR_VARIABLE 選項決定。

產生 Apple 架構選擇檔案

generate_apple_architecture_selection_file

在 3.29 版本中新增。

建立 Apple 架構選擇檔案

generate_apple_architecture_selection_file(<filename>
  INSTALL_DESTINATION <path>
  [INSTALL_PREFIX <path>]
  [SINGLE_ARCHITECTURES <arch>...
   SINGLE_ARCHITECTURE_INCLUDE_FILES <file>...]
  [UNIVERSAL_ARCHITECTURES <arch>...
   UNIVERSAL_INCLUDE_FILE <file>]
  [ERROR_VARIABLE <variable>]
  )

寫入一個檔案,其中包含基於 CMAKE_OSX_ARCHITECTURES 的特定於 Apple 架構的 .cmake 檔案,例如,從特定於 Apple 的 <PackageName>Config.cmake 檔案中包含。

INSTALL_DESTINATION <path>

呼叫端將產生的檔案安裝到的路徑,例如,透過 install(FILES)。 路徑可以是相對於 INSTALL_PREFIX 的相對路徑,也可以是絕對路徑。

INSTALL_PREFIX <path>

呼叫端將套件安裝到的路徑前綴。 <path> 引數必須是絕對路徑。 如果未傳遞此引數,則將改為使用 CMAKE_INSTALL_PREFIX 變數。

SINGLE_ARCHITECTURES <arch>...

SINGLE_ARCHITECTURE_INCLUDE_FILES 的條目提供的架構。

SINGLE_ARCHITECTURE_INCLUDE_FILES <file>...

特定於架構的檔案。 當 CMAKE_OSX_ARCHITECTURES 包含與 SINGLE_ARCHITECTURES 的對應條目匹配的單個架構時,將載入其中一個檔案。

UNIVERSAL_ARCHITECTURES <arch>...

UNIVERSAL_INCLUDE_FILE 提供的架構。

該清單可以包含 $(ARCHS_STANDARD) 以支援使用 Xcode 產生器進行消耗,但架構也應始終單獨列出。

UNIVERSAL_INCLUDE_FILE <file>

CMAKE_OSX_ARCHITECTURES 包含 UNIVERSAL_ARCHITECTURES 的(非嚴格)子集,並且不與任何一個 SINGLE_ARCHITECTURES 匹配時,要載入的檔案。

ERROR_VARIABLE <variable>

如果使用中的專案是為不受支援的架構建置的,則將 <variable> 設定為錯誤訊息。 包含器可以使用此資訊來假裝未找到套件。 如果未給定此選項,則預設行為是發出致命錯誤。

範例產生套件檔案

範例使用 configure_package_config_file()write_basic_package_version_file() 命令

CMakeLists.txt
include(GNUInstallDirs)
set(INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR}/Foo
    CACHE PATH "Location of header files" )
set(SYSCONFIG_INSTALL_DIR ${CMAKE_INSTALL_SYSCONFDIR}/foo
    CACHE PATH "Location of configuration files" )
#...
include(CMakePackageConfigHelpers)
configure_package_config_file(FooConfig.cmake.in
  ${CMAKE_CURRENT_BINARY_DIR}/FooConfig.cmake
  INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/Foo
  PATH_VARS INCLUDE_INSTALL_DIR SYSCONFIG_INSTALL_DIR)
write_basic_package_version_file(
  ${CMAKE_CURRENT_BINARY_DIR}/FooConfigVersion.cmake
  VERSION 1.2.3
  COMPATIBILITY SameMajorVersion )
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/FooConfig.cmake
              ${CMAKE_CURRENT_BINARY_DIR}/FooConfigVersion.cmake
        DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/Foo )
FooConfig.cmake.in
set(FOO_VERSION x.y.z)
...
@PACKAGE_INIT@
...
set_and_check(FOO_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@")
set_and_check(FOO_SYSCONFIG_DIR "@PACKAGE_SYSCONFIG_INSTALL_DIR@")

check_required_components(Foo)