zoukankan      html  css  js  c++  java
  • cmake 的 find_package

    首先,find_package 有两种模式,一是Module模式一是Config模式

    cmake本身不提供任何搜索库的便捷方法,所有搜索库并给变量赋值的操作必须由cmake代码(自己写的)完成,比如下面将要提到的FindXXX.cmake和XXXConfig.cmake。只不过,库的作者通常会提供这两个文件,以方便使用者调用。

    两种搜索模式:(其中 XXX 是模块的名字)

    • Module模式:搜索CMAKE_MODULE_PATH指定路径下的FindXXX.cmake文件,执行该文件从而找到XXX库。其中,具体查找库并给XXX_INCLUDE_DIRSXXX_LIBRARIES两个变量赋值的操作由FindXXX.cmake模块完成。
    • Config模式:搜索XXX_DIR指定路径下的XXXConfig.cmake文件,执行该文件从而找到XXX库。其中具体查找库并给XXX_INCLUDE_DIRSXXX_LIBRARIES两个变量赋值的操作由XXXConfig.cmake模块完成。

    cmake默认采取Module模式,如果Module模式未找到库,才会采取Config模式。如果XXX_DIR路径下找不到XXXConfig.cmake文件,则会找/usr/local/lib/cmake/XXX/中的XXXConfig.cmake文件。总之,Config模式是一个备选策略。通常,库安装时会拷贝一份XXXConfig.cmake到系统目录中,因此在没有显式指定搜索路径时也可以顺利找到。

    若XXX安装时没有安装到系统目录,因此无法自动找到XXXConfig.cmake,可以在CMakeLists.txt最前面添加XXX的搜索路径。

    set(Caffe_DIR /home/hzh/projects/Caffe/build)   #添加CaffeConfig.cmake的搜索路径

    为了能支持各种常见的库和包,CMake自带了很多模块。可以通过命令 cmake –help-module-list (输入cmake –help,然后双击Tab会有命令提示)得到你的CMake支持的模块的列表:直接查看模块路径。比如Ubuntu linux上,模块的路径是 /usr/share/cmake/Modules/

    1、指定 package 搜索辅助文件路径

    list(APPEND CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${CMAKE_CURRENT_LIST_DIR}/cmake")

    set(Caffe_DIR /home/hzh/projects/Caffe/build)   #添加CaffeConfig.cmake的搜索路径

    2、使用 find_package

    https://stackoverflow.com/questions/20746936/what-use-is-find-package-if-you-need-to-specify-cmake-module-path-anyway

    它会自动查找FindXXX.cmakeXXXConfig.cmake文件。

    重要,对Module模式,一般来说,Find<package>.cmake 文件放在自己工程的目录,工程结构如下:

    CMakeLists.txt
    cmake/FindFoo.cmake
    cmake/FindBoo.cmake

    CMakeLists.txt 内容:

    list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
    find_package(Foo REQUIRED) # FOO_INCLUDE_DIR, FOO_LIBRARIES
    find_package(Boo REQUIRED) # BOO_INCLUDE_DIR, BOO_LIBRARIES
    
    include_directories("${FOO_INCLUDE_DIR}")
    include_directories("${BOO_INCLUDE_DIR}")
    add_executable(Bar Bar.hpp Bar.cpp)
    target_link_libraries(Bar ${FOO_LIBRARIES} ${BOO_LIBRARIES})

    请注意,如果系统目录(一般是 /usr/local/lib/cmake/ )里有一个Find<package>.cmake文件,但你却不想使用默认的,想自己定义一个Find<package>.cmake,即想让它绕过默认库,则你可以指定 CMAKE_MODULE_PATH ,它的优先级比默认路径要高。

    Config模式<package>Config.cmake 一般放在外部目录下,也就是说这个文件一般是库的作者写的,库被安装时,该文件被安装在库的安装目录里,供库的使用者直接使用(如果未安装在系统目录,则使用方法是先设置 XXX_DIR,让find_package能找得到XXXConfig.cmake)。示例:

    foo library:

    $ cat CMakeLists.txt 
    cmake_minimum_required(VERSION 2.8)
    project(Foo)
    
    add_library(foo Foo.hpp Foo.cpp)
    install(FILES Foo.hpp DESTINATION include)
    install(TARGETS foo DESTINATION lib)
    install(FILES FooConfig.cmake DESTINATION lib/cmake/Foo)

    Simplified version of config file:

    $ cat FooConfig.cmake 
    add_library(foo STATIC IMPORTED)
    find_library(FOO_LIBRARY_PATH foo HINTS "${CMAKE_CURRENT_LIST_DIR}/../../")
    set_target_properties(foo PROPERTIES IMPORTED_LOCATION "${FOO_LIBRARY_PATH}")

    By default project installed in CMAKE_INSTALL_PREFIX directory:

    $ cmake -H. -B_builds
    $ cmake --build _builds --target install
    -- Install configuration: ""
    -- Installing: /usr/local/include/Foo.hpp
    -- Installing: /usr/local/lib/libfoo.a
    -- Installing: /usr/local/lib/cmake/Foo/FooConfig.cmake

    创建好Foo库之后,如何使用Foo库:

    Use find_package(... CONFIG) to include FooConfig.cmake with imported target foo:

    $ cat CMakeLists.txt 
    cmake_minimum_required(VERSION 2.8)
    project(Boo)
    
    # import library target `foo`
    find_package(Foo CONFIG REQUIRED)
    
    add_executable(boo Boo.cpp Boo.hpp)
    target_link_libraries(boo foo)
    $ cmake -H. -B_builds -DCMAKE_VERBOSE_MAKEFILE=ON $ cmake --build _builds Linking CXX executable Boo /usr/bin/c++ ... -o Boo /usr/local/lib/libfoo.a

    INSTALL 指令

    代码编译后直接make install安装。

    介绍一个新的cmake 指令 INSTALL 和一个非常有用的变量CMAKE_INSTALL_PREFIX。 CMAKE_INSTALL_PREFIX变量类似于configure脚本的 –prefix,常见的使用方法看 起来是这个样子:

    cmake -DCMAKE_INSTALL_PREFIX=/usr .

    INSTALL指令包含了各种安装类型,我们需要一个个分开解释:

    目标文件的安装

    INSTALL(TARGETS targets...
            [[ARCHIVE|LIBRARY|RUNTIME]
                       [DESTINATION <dir>]
                       [PERMISSIONS permissions...]
                       [CONFIGURATIONS
            [Debug|Release|...]]
                       [COMPONENT <component>]
                       [OPTIONAL]
                    ] [...])

    目标类型也就相对应的有三种,ARCHIVE特指静态库,LIBRARY特指动态库,RUNTIME特指可执行目标二进制。参数中的TARGETS后面跟的就是我们通过ADD_EXECUTABLE或者ADD_LIBRARY定义的目标文件,可能是可执行二进制、动态库、静态库。

    DESTINATION定义了安装的路径,如果路径以/开头,那么指的是绝对路径,这时候 CMAKE_INSTALL_PREFIX其实就无效了。如果你希望使用CMAKE_INSTALL_PREFIX来定义安装路径,就要写成相对路径,即不要以/开头,那么安装后的路径就是${CMAKE_INSTALL_PREFIX}/<destination定义的路径>。

    举个例子:

    INSTALL(TARGETS myrun mylib mystaticlib
           RUNTIME DESTINATION bin
           LIBRARY DESTINATION lib
           ARCHIVE DESTINATION libstatic
    )

    上面的例子会将:

    可执行二进制myrun安装到${CMAKE_INSTALL_PREFIX}/bin目录。
    动态库libmylib安装到${CMAKE_INSTALL_PREFIX}/lib目录。
    静态库libmystaticlib安装到${CMAKE_INSTALL_PREFIX}/libstatic目录。
    特别注意的是你不需要关心TARGETS具体生成的路径,只需要写上TARGETS名称就可以了。

    普通文件的安装

    INSTALL(FILES files... DESTINATION <dir>
             [PERMISSIONS permissions...]
             [CONFIGURATIONS [Debug|Release|...]]
             [COMPONENT <component>]
             [RENAME <name>] [OPTIONAL])
    #可用于安装一般文件,并可以指定访问权限,文件名是此指令所在路径下的相对路径。
    #如果默认不定义权限PERMISSIONS,安装后的权限为,OWNER_WRITE,OWNER_READ,
    #GROUP_READ,和WORLD_READ,即644权限。

    非目标文件的可执行程序安装(比如脚本之类)

    INSTALL(PROGRAMS files... DESTINATION <dir>
         [PERMISSIONS permissions...]
         [CONFIGURATIONS [Debug|Release|...]]
         [COMPONENT <component>]
         [RENAME <name>] [OPTIONAL])

    跟上面的FILES指令使用方法一样,唯一的不同是安装后权限为:
    OWNER_EXECUTE, GROUP_EXECUTE, 和WORLD_EXECUTE,即755权限

    目录的安装

    INSTALL(DIRECTORY dirs... DESTINATION <dir>
         [FILE_PERMISSIONS permissions...]
         [DIRECTORY_PERMISSIONS permissions...]
         [USE_SOURCE_PERMISSIONS]
         [CONFIGURATIONS [Debug|Release|...]]
         [COMPONENT <component>]
         [[PATTERN <pattern> | REGEX <regex>]
          [EXCLUDE] [PERMISSIONS permissions...]] [...])

    这里主要介绍其中的DIRECTORY、PATTERN以及PERMISSIONS参数。
    DIRECTORY后面连接的是所在Source目录的相对路径,但务必注意:
    abc和abc/有很大的区别。 abc意味着abc这个目录会安装在目标路径下;abc/意味着abc这个目录的内容会被安装在目标路径下。PATTERN用于使用正则表达式进行过滤, PERMISSIONS用于指定PATTERN过滤后的文件权限。

    看一个例子:

    INSTALL(DIRECTORY icons scripts/ DESTINATION share/myproj
            PATTERN "CVS" EXCLUDE
            PATTERN "scripts/*"
            PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ
            GROUP_EXECUTE GROUP_READ)

    这条指令的执行结果是:

    将icons目录安装到 <prefix>/share/myproj,将scripts/中的内容安装到 <prefix>/share/myproj。
    不包含目录名为CVS的目录,对于scripts/*文件指定权限为 OWNER_EXECUTE 不包含目录名为CVS的目录,对于scripts/*文件指定权限为 OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ。

  • 相关阅读:
    现在分词和过去分词
    VMware Workstation Ubuntu 20.04 LTS无法连接网络问题
    Java中定时器Timer致命缺点(附学习方法)
    2020 年度编程语言排行榜出炉!C 语言称霸,Java 遭遇滑铁卢…….
    人工智能必备数学基础:线性代数基础(1)
    初学VBA
    何同学新视频火了!找到减少沉迷手机的最佳方法:附免费APP
    支付宝蚂蚁森林下线能量提醒功能 产品经理:被骂了、我改
    可抵御所有已知黑客攻击 中国组建天地一体化量子通信网络
    MYSQL数据库 增删改查基础语句
  • 原文地址:https://www.cnblogs.com/welhzh/p/12433802.html
Copyright © 2011-2022 走看看