CMake之find_package

首先强烈推荐对CMake不熟的同学先看这本书《Cmake实践》。

CMake说起来是个好东西,可是真正用的时候并不那么容易,很容易出现各种各样的错误。这不,最近就被find_package这个命令折腾得死去活来。只好花了一天半时间,看上面那本书,再查资料,总算解决了昨天遇到的问题。

问题描述
已经成功编译了深度学习框架Caffe,例程也可以顺利执行。

但是当我在自己的代码中调用编译好的Caffe库时,却出现了编译错误。此前,我已经在CMakeLists.txt中添加了下面几句话:

include_directories(/home/wjg/projects/caffe/build/install/include)
add_executable(useSSD ssd_detect.cpp)
target_link_libraries(useSSD /home/wjg/projects/caffe/build/install/lib/libcaffe.so)
执行make后,链接出错,找不到libboost_system.so文件。

这一错误倒是给我提了个醒,我本以为自己的代码中没用到boost,就不必添加boost库路径了,谁知道libcaffe.so中用到的库也需要手动添加进去。

这时候我才意识到动态链接库和静态链接库的区别。前者在程序运行时动态加载,而后者是在编译时就和程序结合到一起了。于是动态链接库即使编译完成,也和其它动态库是分离的,因此每次用都要把所有涉及的动态库全部添加进来。在我的例子中,不仅仅需要添加boost,还有atlas、protobuf等等一大堆动态链接库需要添加。这个时候,一条条添加就显得太过麻烦,可以借助find_package命令一次性添加所有与Caffe相关的动态链接库。

find_package用法
使用如下方式查找Caffe库:

find_package(Caffe REQUIRED)
如果找到Caffe库,就可以在接下来的语句中使用Caffe_INCLUDE_DIRS和Caffe_LIBRARIES这两个变量,比如

find_package(Caffe REQUIRED)

if (NOT Caffe_FOUND)
message(FATAL_ERROR “Caffe Not Found!”)
endif (NOT Caffe_FOUND)

include_directories(${Caffe_INCLUDE_DIRS})

add_executable(useSSD ssd_detect.cpp)
target_link_libraries(useSSD ${Caffe_LIBRARIES})
问题是,很多情况下都会找不着,或者找到了错误的位置。要想用对find_package,就需要了解它的工作原理。

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

find_package采用两种模式搜索库:

Module模式:搜索CMAKE_MODULE_PATH指定路径下的FindXXX.cmake文件,执行该文件从而找到XXX库。其中,具体查找库并给XXX_INCLUDE_DIRS和XXX_LIBRARIES两个变量赋值的操作由FindXXX.cmake模块完成。
Config模式:搜索XXX_DIR指定路径下的XXXConfig.cmake文件,执行该文件从而找到XXX库。其中具体查找库并给XXX_INCLUDE_DIRS和XXX_LIBRARIES两个变量赋值的操作由XXXConfig.cmake模块完成。
两种模式看起来似乎差不多,不过cmake默认采取Module模式,如果Module模式未找到库,才会采取Config模式。如果XXX_DIR路径下找不到XXXConfig.cmake文件,则会找/usr/local/lib/cmake/XXX/中的XXXConfig.cmake文件。总之,Config模式是一个备选策略。通常,库安装时会拷贝一份XXXConfig.cmake到系统目录中,因此在没有显式指定搜索路径时也可以顺利找到。

在我遇到的问题中,由于Caffe安装时没有安装到系统目录,因此无法自动找到CaffeConfig.cmake,我在CMakeLists.txt最前面添加了一句话之后就可以了。

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

find_package(Caffe REQUIRED)

if (NOT Caffe_FOUND)
message(FATAL_ERROR “Caffe Not Found!”)
endif (NOT Caffe_FOUND)

include_directories(${Caffe_INCLUDE_DIRS})

add_executable(useSSD ssd_detect.cpp)
target_link_libraries(useSSD ${Caffe_LIBRARIES})
其实关于find_package还有许多知识点,可惜我也没能全部掌握。XXXConfig.cmake的默认搜索路径也不止一个,它们有详细的优先级顺序。对于库的开发者来说,如何生成FindXXX.cmake或XXXConfig.cmake文件更是一个复杂工程,需要了解更多的知识,希望以后有机会再深入了解。

作者:金戈大王
链接:https://www.jianshu.com/p/46e9b8a6cb6a
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`find_package` 是 CMake 中用于查找和加载外部依赖库的命令。它会在系统中搜索指定名称的库,并自动配置编译选项。一般情况下,我们需要在 CMakeLists.txt 文件中使用 `find_package` 命令来查找我们需要的库,然后将它们链接到我们的项目中。 下面是使用 `find_package` 命令的一般步骤: 1. 在 CMakeLists.txt 文件中使用 `find_package` 命令,指定要查找的库的名称和版本。 例如,要查找 Boost 库,可以使用以下命令: ``` find_package(Boost 1.46 REQUIRED COMPONENTS system thread) ``` 2. 如果库没有被找到,可以通过设置 `CMAKE_PREFIX_PATH` 环境变量或者 `CMAKE_MODULE_PATH` 变量来指定库的安装路径或者 CMake 模块所在路径。 3. 如果找到了库,`find_package` 命令会自动定义一些变量,用于指定库的路径、头文件路径和库文件路径等信息。 例如,对于 Boost 库,`find_package` 命令会定义以下变量: ``` Boost_FOUND Boost_INCLUDE_DIRS Boost_LIBRARY_DIRS Boost_LIBRARIES ``` 4. 在项目中使用这些变量,例如: ``` include_directories(${Boost_INCLUDE_DIRS}) link_directories(${Boost_LIBRARY_DIRS}) target_link_libraries(my_target ${Boost_LIBRARIES}) ``` 这些变量包含了库的路径信息,可以用来编译和链接项目。 需要注意的是,`find_package` 命令只能用于已经被 CMake 支持的库。对于一些非常规的库,可能需要手动配置编译选项来使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值