10.4-CMake find 模塊


CMake 專題: How to find Libraries

前言

參考

cmake wiki: how to find libraries
How_to_create_a_ProjectConfig.cmake_file
cmake documentation: home page
Find package example
Martin K, Hoffman B. Mastering CMake[M]. Kitware, 2015.

學習記錄

基礎知識

  • 使用VERBOSE=1來檢查各種構建選項。
  • 在/build/Release/.../CMakeFiles/${cmake_target}.dir/中,有四個文件,用作CMake對依賴項的分析:
    • depend.make:存儲依賴項信息
    • flag.make:存儲編譯選項,如果該文件改變,將重新編譯
    • build.make:依賴項如何構建,如果該文件改變,CMake將重新計算依賴
    • DependInfo.cmake:當前項目中有哪些文件和哪些語言
  • add_library(foo STATIC foo1.c foo2.c)
    • 注意第一個參數是目標名,第二個參數是目標的修飾詞,如果沒有這個修飾詞,那么將檢查環境變量BUILD_SHARED_LIBS,如果沒有定義這個環境變量,則按默認,生成靜態鏈接庫
  • target_link_libraries(foo bar)
    • bar可為:庫名字,庫的完整路徑名和之前用add_library()指令生成的庫名
  • 環境變量有局部特性:意味着子函數,子路徑,子CMake指令中的變量名字不會影響上一個環境
  • 函數舉例
function(foo)
    message(${test}) # test is 1 here
    set(test 2 PARENT_SCOPE)
    message(${test}) # test is still 1 in this scope
endfunction()

set(test 1)
foo()
message(${test}) # test will now be 2 here
  • 循環舉例
set (items_to_buy apple orange pear beer)
foreach (item ${items_to_buy})
    message("Don't forget to buy one ${item}")
endforeach()
  • CMake Cache
    • 作用:緩存,下一次可以直接用;人機界面使用這個信息
    • 注意:一旦Cache中有了信息,則只能通過人機界面來修改?
    • 用法:option(USE_JPEG "DO you want to use jepg library?"),這句話會創建一個變量名存入Cache。
    • 直接使用CACHE option
    • set(USE_JPEG ON CACHE BOOL "include jpeg support?")
    • ON:變量值;CACHE:選項;BOOL:變量類型;"include jepg ...":文檔字符串
find_library(TIFF_LIBRARY
                NAMES tiff tiff2
                PATHS /usr/local/lib /usr/lib
                )
find_path(TIFF_INCLUDES tiff.h
                /usr/local/include
                /usr/include
                )
include_directories(${TIFF_INCLUDES})
add_executable(mytiff mytiff.c)
target_link_libraries(myprogram ${TIFF_LIBRARY})
  • find_library
    • 當不同的系統,相同的庫文件被安裝在不同路徑下時,就需要使用這個命令
    • 只需要庫的base name,即不需要libtiff,libtiff2,或者tiff.so,tiff.so.2
    • find命令,會去${PATH}里面找文件
    • 命令會默認創建CACHE
  • find_path
    • 當不同的系統,相同的頭文件被安裝在不同路徑下時,就需要使用這個命令
    • 其他和find_library差不多
  • find_package
    • ./Modules/里面有默認的FindXX.cmake,運行這個命令就相當於運行這個.cmake文件,如果找到模塊,則賦予多個環境變量值

find_package詳解

使用外部庫

  • CMake原生支持許多module的尋找,通過cmake --help-modul-list,可以查看,相關原生.cmake文件存放在/usr/share/cmake/Modules/

如果在網上找到了FindXXX.cmake文件

  • 第一步,檢查這個包是否是必須的,如果不是必須,將REQUIRED關鍵字去掉即可
  • 如果該包必須,則將此文件放入你的當前項目的./cmake/modules/中,然后在根目錄的CMakeLists文件中,添加
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")

帶有組件的庫

  • 注意,以下句子都是等同的
find_package(Qt COMPONENTS QtOpenGL QtXml REQUIRED)

find_package(Qt COMPONENTS QtOpenGL QtXml REQUIRED)
find_package(Qt REQUIRED COMPONENTS QtOpenGL QtXml)
find_package(Qt REQUIRED QtOpenGL QtXml)
  • 會產生 _ _FOUND

find_package工作機制

  • 尋找Findxxx.cmake文件,首先到${CMAKE_MODULE_PATH}中找,然后在自己的/modules/中找。
  • 如果沒有找到,則尋找 Config.cmake or -config.cmake,這些是一些庫在安裝時候自動生成的,不過一般不會被生成。
  • 找到之后,生成以下變量
    • _FOUND
    • _INCLUDE_DIRS or _INCLUDES
    • _LIBRARIES or _LIBRARIES or _LIBS
    • _DEFINITIONS

pkg-config

  • 當某一個庫沒有內建cmake支持時,無法生成Findxxx.cmake文件進行搜索,可以借助這個工具進行尋找。
  • 不過請注意:這個工具生成的結果不可靠

自己寫findxxx.cmake

傳統方法

  • 注意,該文件名需要符合特定的規則
  • 使用find_package命令來找到這個包的依賴項。
  • 使用pkd-config來檢測包含文件/庫文件的目錄
  • 使用find_path和find_library來確定庫文件和頭文件
    • pkg-config的生成結果可以作為候選搜索目錄
    • 添加一些一定會存在的目錄
    • 命令執行后會生成變量
  • Set _INCLUDE_DIRS to _INCLUDE_DIR _INCLUDE_DIRS ...
  • Set _LIBRARIES to _LIBRARY _LIBRARIES ...
  • Call the find_package_handle_standard_args() macro to set the _FOUND variable and print a success or failure message.
# - Try to find LibXml2
# Once done this will define
#  LIBXML2_FOUND - System has LibXml2
#  LIBXML2_INCLUDE_DIRS - The LibXml2 include directories
#  LIBXML2_LIBRARIES - The libraries needed to use LibXml2
#  LIBXML2_DEFINITIONS - Compiler switches required for using LibXml2

find_package(PkgConfig)
pkg_check_modules(PC_LIBXML QUIET libxml-2.0)
set(LIBXML2_DEFINITIONS ${PC_LIBXML_CFLAGS_OTHER})

find_path(LIBXML2_INCLUDE_DIR libxml/xpath.h
          HINTS ${PC_LIBXML_INCLUDEDIR} ${PC_LIBXML_INCLUDE_DIRS}
          PATH_SUFFIXES libxml2 )

find_library(LIBXML2_LIBRARY NAMES xml2 libxml2
             HINTS ${PC_LIBXML_LIBDIR} ${PC_LIBXML_LIBRARY_DIRS} )

include(FindPackageHandleStandardArgs)
# handle the QUIETLY and REQUIRED arguments and set LIBXML2_FOUND to TRUE
# if all listed variables are TRUE
find_package_handle_standard_args(LibXml2  DEFAULT_MSG
                                  LIBXML2_LIBRARY LIBXML2_INCLUDE_DIR)

mark_as_advanced(LIBXML2_INCLUDE_DIR LIBXML2_LIBRARY )

set(LIBXML2_LIBRARIES ${LIBXML2_LIBRARY} )
set(LIBXML2_INCLUDE_DIRS ${LIBXML2_INCLUDE_DIR} )

借助LibFindMacros宏

# - Try to find ImageMagick++
# Once done, this will define
#
#  Magick++_FOUND - system has Magick++
#  Magick++_INCLUDE_DIRS - the Magick++ include directories
#  Magick++_LIBRARIES - link these to use Magick++

include(LibFindMacros)

# Dependencies
libfind_package(Magick++ Magick)

# Use pkg-config to get hints about paths
libfind_pkg_check_modules(Magick++_PKGCONF ImageMagick++)

# Include dir
find_path(Magick++_INCLUDE_DIR
  NAMES Magick++.h
  PATHS ${Magick++_PKGCONF_INCLUDE_DIRS}
)

# Finally the library itself
find_library(Magick++_LIBRARY
  NAMES Magick++
  PATHS ${Magick++_PKGCONF_LIBRARY_DIRS}
)

# Set the include dir variables and the libraries and let libfind_process do the rest.
# NOTE: Singular variables for this library, plural for libraries this this lib depends on.
set(Magick++_PROCESS_INCLUDES Magick++_INCLUDE_DIR Magick_INCLUDE_DIRS)
set(Magick++_PROCESS_LIBS Magick++_LIBRARY Magick_LIBRARIES)
libfind_process(Magick++)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM