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
檔案可重新定位。 用法
像平常一樣編寫
FooConfig.cmake.in
檔案。在頂部插入一行,僅包含字串
@PACKAGE_INIT@
。不要使用
set(FOO_DIR "@SOME_INSTALL_DIR@")
,而是使用set(FOO_DIR "@PACKAGE_SOME_INSTALL_DIR@")
(這必須在@PACKAGE_INIT@
行之後)。不要使用普通的
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 版本中新增: AnyNewerVersion
、SameMajorVersion
和 SameMinorVersion
引數的 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)