步驟 11:新增匯出組態¶
在教學的安裝 與 測試
期間,我們新增了讓 CMake 安裝專案的程式庫和標頭檔的功能。在封裝 安裝程式
期間,我們新增了封裝此資訊的功能,以便將其散佈給其他人。
下一步是新增必要的資訊,以便其他 CMake 專案可以使用我們的專案,無論是從建置目錄、本機安裝還是封裝。
第一步是更新我們的 install(TARGETS)
命令,不僅指定 DESTINATION
,還指定 EXPORT
。EXPORT
關鍵字會產生一個 CMake 檔案,其中包含從安裝樹狀結構匯入安裝命令中列出的所有目標的程式碼。因此,讓我們繼續明確地 EXPORT
MathFunctions
程式庫,方法是更新 MathFunctions/CMakeLists.txt
中的 install
命令,使其看起來像這樣
set(installable_libs MathFunctions tutorial_compiler_flags)
if(TARGET SqrtLibrary)
list(APPEND installable_libs SqrtLibrary)
endif()
install(TARGETS ${installable_libs}
EXPORT MathFunctionsTargets
DESTINATION lib)
# install include headers
install(FILES MathFunctions.h DESTINATION include)
現在我們已經匯出 MathFunctions
,我們還需要明確安裝產生的 MathFunctionsTargets.cmake
檔案。這可以透過將以下內容新增到頂層 CMakeLists.txt
的底部來完成
install(EXPORT MathFunctionsTargets
FILE MathFunctionsTargets.cmake
DESTINATION lib/cmake/MathFunctions
)
此時,您應該嘗試執行 CMake。如果一切設定正確,您將看到 CMake 將產生一個如下所示的錯誤
Target "MathFunctions" INTERFACE_INCLUDE_DIRECTORIES property contains
path:
"/Users/robert/Documents/CMakeClass/Tutorial/Step11/MathFunctions"
which is prefixed in the source directory.
CMake 正在告訴您,在產生匯出資訊期間,它將匯出一個本質上與目前機器相關的路徑,並且在其他機器上將無效。解決方案是更新 MathFunctions
target_include_directories()
以了解當從建置目錄以及從安裝/封裝中使用時,它需要不同的 INTERFACE
位置。這表示轉換 target_include_directories()
對 MathFunctions
的呼叫,使其看起來像這樣
target_include_directories(MathFunctions
INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:include>
)
更新完成後,我們可以重新執行 CMake 並驗證它不再發出警告。
此時,我們已經讓 CMake 正確封裝了所需的目標資訊,但我們仍然需要產生一個 MathFunctionsConfig.cmake
,以便 CMake find_package()
命令可以找到我們的專案。因此,讓我們繼續在專案的頂層新增一個名為 Config.cmake.in
的新檔案,內容如下
@PACKAGE_INIT@
include ( "${CMAKE_CURRENT_LIST_DIR}/MathFunctionsTargets.cmake" )
然後,為了正確設定和安裝該檔案,請將以下內容新增到頂層 CMakeLists.txt
的底部
install(EXPORT MathFunctionsTargets
FILE MathFunctionsTargets.cmake
DESTINATION lib/cmake/MathFunctions
)
include(CMakePackageConfigHelpers)
接下來,我們執行 configure_package_config_file()
。此命令將設定提供的檔案,但與標準 configure_file()
方式有一些具體差異。為了正確使用此函數,輸入檔案應該只有一行文字 @PACKAGE_INIT@
,以及所需的內容。該變數將被替換為一個程式碼區塊,該區塊將設定的值轉換為相對路徑。這些新的值可以使用相同的名稱來引用,但在前面加上 PACKAGE_
前綴。
install(EXPORT MathFunctionsTargets
FILE MathFunctionsTargets.cmake
DESTINATION lib/cmake/MathFunctions
)
include(CMakePackageConfigHelpers)
# generate the config file that includes the exports
configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in
"${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfig.cmake"
INSTALL_DESTINATION "lib/cmake/MathFunctions"
NO_SET_AND_CHECK_MACRO
NO_CHECK_REQUIRED_COMPONENTS_MACRO
)
write_basic_package_version_file()
是下一步。此命令會寫入一個檔案,該檔案由 find_package()
使用,記錄所需套件的版本和相容性。在這裡,我們使用 Tutorial_VERSION_*
變數,並表示它與 AnyNewerVersion
相容,這表示此版本或任何更高版本都與請求的版本相容。
write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfigVersion.cmake"
VERSION "${Tutorial_VERSION_MAJOR}.${Tutorial_VERSION_MINOR}"
COMPATIBILITY AnyNewerVersion
)
最後,設定要安裝的兩個產生檔案
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfig.cmake
${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfigVersion.cmake
DESTINATION lib/cmake/MathFunctions
)
此時,我們已經為我們的專案產生了一個可重新定位的 CMake 組態,該組態可以在專案安裝或封裝後使用。如果我們也希望從建置目錄中使用我們的專案,我們只需要將以下內容新增到頂層 CMakeLists.txt
的底部
export(EXPORT MathFunctionsTargets
FILE "${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsTargets.cmake"
)
透過此匯出呼叫,我們現在產生一個 MathFunctionsTargets.cmake
,允許建置目錄中設定的 MathFunctionsConfig.cmake
被其他專案使用,而無需安裝它。