cmake 學習筆記(三)

學習一下cmake的 finder。

finder是神馬東西?

當編譯一個需要使用第三方庫的軟件時,我們需要知道:

去哪兒找頭文件 .h

對比GCC的 -I 參數

去哪兒找庫文件 (.so/.dll/.lib/.dylib/...)

對比GCC的 -L 參數

需要鏈接的庫文件的名字

對比GCC的 -l 參數

這也是一個 finder 需要返回的最基本的信息。

如何使用?

比如說,我們需要一個第三方庫 curl,那麼我們的 CMakeLists.txt 需要指定頭文件目錄,和庫文件,類似:

include_directiories(/usr/include)
target_link_libraries(myprogram curl)

如果藉助於cmake提供的finder會怎麼樣呢?使用cmake的Modules目錄下的FindCURL.cmake,相應的 CMakeList.txt 文件:

find_package(CURL REQUIRED)
include_directories(${CURL_INCLUDE_DIR})
target_link_libraries(curltest ${CURL_LIBRARY})

或者

find_package(CURL)
if(CURL_FOUND)
include_directories(${CURL_INCLUDE_DIR})
target_link_libraries(curltest ${CURL_LIBRARY})
else(CURL_FOUND)
message(FATAL_ERROR "curl not found!")
endif(CURL_FOUND)

如果我們使用的finder,不是cmake自帶的怎麼辦?

  • 放置位置:工程根目錄下的 cmake/Modules/
  • 然後在 CMakeList.txt 中添加
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")

find_package如何工作

find_package 將會在module路徑下查找 Find<name>.cmake。首先它搜索 ${CMAKE_MODULE_PATH}中的所有路徑,然後搜索 <CMAKE_ROOT>/share/cmake-x.y/Modules/

如果這個文件未找到,它將會查找 <Name>Config.cmake 或 <lower-case-name>-config.cmake 文件。這兩個文件是庫文件安裝時自己安裝的,將自己的路徑硬編碼到其中。

前者稱爲 module 模式,後者稱爲 config 模式

每個模塊一般都會提供一下幾個變量

  • <name>_FOUND

  • <name>_INCLUDE_DIR 或 <name>_INCLUDES

  • <name>_LIBRARY 或 <name>_LIBRARIES 或 <name>_LIBS

  • <name>_DEFINITIONS

編寫finder

  • 首先使用 find_package 探測本軟件包依賴的第三方庫(參數 QUIETLY 和 REQUIRED應該被傳遞)
  • 如果 pkg-config 可用,則可以用其去探測include/library路徑
  • 分別使用 find_path 和 find_library 查找頭文件和庫文件
    • pkg-config 提供的路徑僅作爲參考
    • CMake 有很多硬編碼的路徑
    • 結果放到 <name>_INCLUDE_DIR 和 <name>_LIBRARY (注意:單數而不是複數)

  • 設置 <name>_INCLUDE_DIRS 爲 <name>_INCLUDE_DIR <dependency1>_INCLUDE_DIRS ...

  • 設置 <name>_LIBRARIES 爲 <name>_LIBRARY <dependency1>_LIBRARIES ...

    • 依賴使用複數,包自身使用單數形式(由find_path和find_library提供)
  • 調用宏 find_package_handle_standard_args() 設置 <name>_FOUND 並打印或失敗信息

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章