• 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++)
  • 相关阅读:
    vue与mui起冲突
    pc端使用微信登陆
    文字显示两行,多余的省略号(兼容搜狐)
    ios input 添加 readonly 属性,光标依旧还在的解决办法
    调用微信扫一扫接口扫描二维码
    js搜索框实现自动搜索功能
    跳转页面的几种方法
    关于清空object对象里的属性的两种方法
    http://stormzhang.com/opensource/2016/06/26/android-open-source-project-recommend1/
    给 Android 初学者的 Gradle 知识普及
  • 原文地址:https://www.cnblogs.com/lizhensheng/p/11117219.html
Copyright © 2020-2023  润新知