CMake中find_package指令的實現(xiàn)
1.簡介
查找模塊(find module)是一系列用于搜索第三方依賴軟件包(包括庫或可執(zhí)行文件)的模塊。對查找模塊的引用一般不使用include命令,而是使用find_package命令。
基本語法
find_package(<PackageName> [version] [EXACT] [QUIET] [MODULE]
[REQUIRED] [[COMPONENTS] [components...]]
[OPTIONAL_COMPONENTS components...]
[CONFIG|NO_MODULE]
[HINTS path1 [path2 ... ]]
[PATHS path1 [path2 ... ]]
[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]
[NO_CMAKE_SYSTEM_PATH]
[CMAKE_FIND_ROOT_PATH_BOTH|ONLY_CMAKE_FIND_ROOT_PATH|NO_CMAKE_FIND_ROOT_PATH])常用簡化形式:
find_package(Boost 1.70 REQUIRED COMPONENTS system filesystem) find_package(OpenCV REQUIRED)
2.搜索模式
find_package 支持兩種搜索模式:
1. 模塊模式(Module Mode)
- 使用 CMake 內(nèi)置的模塊文件(位于 Modules/Find<PackageName>.cmake)來完成對軟件包的搜索。它首先在CMAKE_MODULE_PATH變量定義的路徑列表中搜索查找模塊,若找不到,則從CMake安裝目錄中搜索符合該名稱的CMake預(yù)制的查找模塊。如果任未找到對應(yīng)的查找模塊,該命令會切換到配置模式再進行處理。
- 適用于沒有提供 CMake 配置文件的舊庫(如 OpenGL、Boost 部分組件)。
- 模塊文件由用戶或 CMake 官方編寫,通過手動邏輯查找?guī)斓念^文件目錄(find_path)、庫文件(find_library),并定義 <PackageName>_FOUND、<PackageName>_INCLUDE_DIRS、<PackageName>_LIBRARIES 等變量。
2.配置模式(Config Mode)
- 查找?guī)熳詭У?CMake 配置文件(如 <PackageName>Config.cmake 或<PackageName>-config.cmake 或 <PackageName>ConfigVersion.cmake)。
- 適用于現(xiàn)代庫(如 OpenCV、Qt、Eigen)。
- 配置文件由庫的編譯安裝流程生成,會自動導(dǎo)出導(dǎo)入目標(biāo)(如 <PackageName>::<TargetName>),并封裝頭文件、庫文件、編譯選項等信息,無需手動定義變量。
模式選擇規(guī)則:
- 默認(rèn)優(yōu)先嘗試 配置模式,失敗后嘗試 模塊模式。
- 通過 CONFIG 或 NO_MODULE 參數(shù)強制使用配置模式。
- 通過 MODULE 參數(shù)強制使用模塊模式。如:
find_package(PackageName MODULE) # 強制使用模塊模式
3.常用參數(shù)
| 參數(shù) | 作用 |
|---|---|
| REQUIRED | 表示該軟件包是構(gòu)建過程中所必須的,找不到包時終止配置并報錯。 |
| QUIET | 用于啟用靜默模式,找不到包時不顯示警告(默認(rèn)會顯示警告)。 |
| EXACT | 要求版本嚴(yán)格匹配(如 3.14.1)。 |
| COMPONENTS | 指定需要的組件(如 Boost 的 system、filesystem)。 |
| HINTS | 手動指定可能的搜索路徑(優(yōu)先級高于默認(rèn)路徑)。 |
| PATHS | 強制搜索特定路徑(優(yōu)先級最高)。 |
| NO_DEFAULT_PATH | 不搜索任何默認(rèn)路徑(僅使用 HINTS 和 PATHS)。 |
4.工作流程
1.確定搜索路徑
- 系統(tǒng)默認(rèn)路徑(如 /usr/lib/cmake、C:/Program Files/<PackageName>)。
- CMAKE_PREFIX_PATH 環(huán)境變量指定的路徑。
- HINTS 和 PATHS 參數(shù)指定的路徑。
2.查找配置文件
- 配置模式:查找 <PackageName>Config.cmake 或 <lowercase-package-name>-config.cmake。
- 模塊模式:查找 CMake 內(nèi)置的 Find<PackageName>.cmake 模塊。
這里也可以自定義搜索路徑:
find_package(MyLib REQUIRED
HINTS ${CMAKE_SOURCE_DIR}/../mylib/install # 優(yōu)先搜索此路徑
PATHS /opt/mylib /usr/local/mylib # 備選路徑
)3.驗證版本(若指定)
- 檢查庫版本是否滿足要求(如 >=3.10 或 EXACT 3.14.1)。
4.導(dǎo)入目標(biāo)
成功后,CMake 會定義一系列變量和導(dǎo)入目標(biāo)(如 <PackageName>::<Component>)。
設(shè)置結(jié)果變量
通過 find_package_handle_standard_args 命令,根據(jù)搜索結(jié)果設(shè)置以下關(guān)鍵變量:
- <PackageName>_FOUND:是否找到庫(TRUE/FALSE)。
- <PackageName>_INCLUDE_DIRS 或 <PackageName>_INCLUDES:頭文件路徑。
- <PackageName>_LIBRARIES 或 <PackageName>_LIBS:庫文件路徑。
- <PackageName>_VERSION:庫版本號。
創(chuàng)建導(dǎo)入目標(biāo)(配置模式推薦)
現(xiàn)代模塊文件(如 FindBoost.cmake)會額外創(chuàng)建導(dǎo)入目標(biāo)(如 Boost::system),允許通過 target_link_libraries 直接鏈接。
find_package(OpenCV REQUIRED)
target_link_libraries(myapp PRIVATE ${OpenCV_LIBS}) # 模塊模式
# 或
target_link_libraries(myapp PRIVATE OpenCV::opencv_core) # 配置模式5.內(nèi)置模塊示例:FindBoost.cmake
以查找 Boost 庫為例,模塊模式的典型用法如下:
1. 調(diào)用 find_package
find_package(Boost 1.70 REQUIRED COMPONENTS system filesystem)
2. 模塊文件的行為
FindBoost.cmake 會:
- 搜索 Boost 的頭文件路徑(如 /usr/include/boost)。
- 搜索指定組件的庫文件(如 libboost_system.so、libboost_filesystem.so)。
- 設(shè)置變量:
Boost_FOUND # 是否找到所有必需組件 Boost_INCLUDE_DIRS # 頭文件路徑 Boost_LIBRARIES # 庫文件列表(如 boost_system;boost_filesystem) Boost_VERSION # 版本號(如 1.70.0)
3.在項目中使用結(jié)果
if(Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
target_link_libraries(myapp PRIVATE ${Boost_LIBRARIES})
# 或使用導(dǎo)入目標(biāo)(若模塊支持)
# target_link_libraries(myapp PRIVATE Boost::system Boost::filesystem)
endif()6.自定義模塊文件(Find<PackageName>.cmake)
若依賴庫沒有內(nèi)置的 Find<PackageName>.cmake,可手動編寫模塊文件。以下是一個簡化的 FindMyLib.cmake 示例:
# 1. 定義緩存變量,允許用戶手動指定路徑
set(MYLIB_ROOT "" CACHE PATH "MyLib installation root")
# 2. 查找頭文件
find_path(MYLIB_INCLUDE_DIR
NAMES mylib.h
HINTS ${MYLIB_ROOT}/include
PATHS /usr/local/include /opt/mylib/include
)
# 3. 查找?guī)煳募o態(tài)庫)
find_library(MYLIB_LIBRARY
NAMES mylib mylib_static
HINTS ${MYLIB_ROOT}/lib
PATHS /usr/local/lib /opt/mylib/lib
)
# 4. 驗證版本(示例:從頭文件中提取版本)
if(MYLIB_INCLUDE_DIR)
file(STRINGS "${MYLIB_INCLUDE_DIR}/mylib.h" MYLIB_VERSION_LINE
REGEX "#define MYLIB_VERSION \"[0-9.]+\"")
string(REGEX REPLACE "#define MYLIB_VERSION \"([0-9.]+)\"" "\\1"
MYLIB_VERSION "${MYLIB_VERSION_LINE}")
endif()
# 5. 設(shè)置標(biāo)準(zhǔn)結(jié)果變量
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(MyLib
REQUIRED_VARS MYLIB_LIBRARY MYLIB_INCLUDE_DIR
VERSION_VAR MYLIB_VERSION
)
# 6. 可選:創(chuàng)建導(dǎo)入目標(biāo)(現(xiàn)代 CMake 推薦)
if(MYLIB_FOUND)
add_library(MyLib::MyLib UNKNOWN IMPORTED)
set_target_properties(MyLib::MyLib PROPERTIES
IMPORTED_LOCATION "${MYLIB_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES "${MYLIB_INCLUDE_DIR}"
)
endif()使用自定義模塊:
# 添加模塊路徑到 CMAKE_MODULE_PATH
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/modules")
# 調(diào)用 find_package
find_package(MyLib 2.0 REQUIRED)
# 鏈接導(dǎo)入目標(biāo)(或使用變量)
target_link_libraries(myapp PRIVATE MyLib::MyLib)7.模塊模式 vs 配置模式
| 特性 | 模塊模式 | 配置模式 |
|---|---|---|
| 依賴文件 | CMake 內(nèi)置 / 用戶自定義的 Find<>.cmake | 庫自身提供的 <>.cmake 或 <>.Config.cmake |
| 維護者 | CMake 社區(qū)或用戶 | 庫開發(fā)者 |
| 變量命名 | 不統(tǒng)一(如 Boost_LIBRARIES vs OpenCV_LIBS) | 統(tǒng)一(通過導(dǎo)入目標(biāo)) |
| 推薦場景 | 舊庫、無 CMake 支持的庫 | 現(xiàn)代庫(如 Qt、Eigen) |
| 集成度 | 較低(需手動處理變量) | 較高(自動生成導(dǎo)入目標(biāo)) |
8.總結(jié)
1.優(yōu)先使用配置模式:現(xiàn)代庫通常提供自己的 CMake 配置文件(如 Qt5Config.cmake),通過導(dǎo)入目標(biāo)(如 Qt5::Core)可自動處理頭文件路徑和鏈接依賴,避免變量污染。
2.模塊模式的局限性:模塊文件由第三方維護(如 CMake 社區(qū)),可能存在版本滯后或配置不完整的問題(如缺少某些組件)。
3.自定義模塊的注意事項
- 使用 find_package_handle_standard_args 統(tǒng)一結(jié)果變量。
- 為庫創(chuàng)建導(dǎo)入目標(biāo)(IMPORTED 目標(biāo)),與現(xiàn)代 CMake 風(fēng)格兼容。
- 通過 CACHE 變量允許用戶手動指定路徑(如 MYLIB_ROOT)。
模塊模式是 CMake 兼容舊庫或無 CMake 支持庫的重要機制,通過 Find<PackageName>.cmake 模塊文件實現(xiàn)依賴查找。盡管配置模式更現(xiàn)代,但模塊模式在兼容傳統(tǒng)項目時仍不可替代。在實際開發(fā)中,建議優(yōu)先使用配置模式,僅在必要時通過自定義模塊支持舊庫。
相關(guān)鏈接
- CMake 官網(wǎng) CMake - Upgrade Your Software Build System
- CMake 官方文檔:CMake Tutorial — CMake 4.0.2 Documentation
- CMake 源碼:https://github.com/Kitware/CMake
- CMake 源碼:CMake · GitLab
- 中文版基礎(chǔ)介紹: CMake 入門實戰(zhàn) | HaHack
- wiki: Home · Wiki · CMake / Community · GitLab
到此這篇關(guān)于CMake中find_package指令的實現(xiàn)的文章就介紹到這了,更多相關(guān)CMake find_package指令內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語言鏈表實現(xiàn)學(xué)生信息管理系統(tǒng)程序設(shè)計
這篇文章主要為大家詳細(xì)介紹了C語言鏈表實現(xiàn)學(xué)生信息管理系統(tǒng)程序設(shè)計,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-07-07
手把手帶你學(xué)習(xí)C++的數(shù)據(jù)類型
這篇文章主要為大家介紹了C++的數(shù)據(jù)類型,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助,希望能夠給你帶來幫助2021-11-11
c語言實現(xiàn)數(shù)組循環(huán)左移m位
這篇文章主要介紹了c語言實現(xiàn)數(shù)組循環(huán)左移m位,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-07-07

