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>] )
當為安裝專案或函式庫建立 <PackageName>Config.cmake
或 <PackageName>-config.cmake
檔案時,應使用 configure_package_config_file()
取代一般的 configure_file()
命令。這有助於使產生的套件可重新定位,方法是避免在已安裝的 <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()
巨集。
應在 FooConfig.cmake
檔案的結尾呼叫 check_required_components(<PackageName>)
。此巨集會檢查是否已找到所有請求的非可選元件,如果不是這種情況,則會將 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 版本中新增: 由 COMPATIBILITY
的 AnyNewerVersion
、SameMajorVersion
和 SameMinorVersion
引數產生的版本檔案會處理版本範圍(如果指定了範圍)(請參閱 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)