调用C++库,一般需要其库文件和头文件
可以通过CMake编译C++源文件,然后自行生成C++库文件和头文件供其它程序调用
cmake -D CMAKE_INSTALL_PREFIX="/some/where/local" ..
安装:使用cmake命令,把C++源文件编译生成的bin文件和lib文件安装在了/some/where/local下
使用:在调用这个C++库的时候,CMakeLists.txt 中使用 find_package(Ceres REQUIRED PATHS "/some/where/local/ ")才会找到 Ceres 库的头文件、库文件。
注意: 这种安装方式可以适用于多版本 Ceres 的使用,如果安装了两个 Ceres 在不同的目录中,那么在使用的过程中,我们只要在 find_package( ) 中 PATHS 后面指定其中一个版本的安装路径即可。
cmake -D EXPORT_BUILD_DIR=ON ..
安装:使用cmake命令,对C++源文件编译安装,这种方式会让 HOME 目录下的 .cmake 中出现 packages/Ceres 文件夹。
.cmake文件有什么用:Ceres 文件夹里有一个文件,该文件记录了包含 CeresConfig.cmake
的地址,一般是编译 Ceres 的原始目录地址,比如这里的 build 目录所在的绝对路径,然后CMake 会根据该文件提供的路径找到CeresConfig.cmake
文件,进而利用CeresConfig.cmake
中的语句,找到 Ceres 库的头文件和库文件。这个是 cmake 特有的搜索方式。即.cmake文件中包含了该库的头文件和库文件的路径。
使用:可以直接在 CMakeLists.txt 中 find_package(Ceres REQUIRED) 了。
调用:find_package() 本质上是在查找 CeresConfig.cmake 这个文件,有不同的 cmake 搜索路径,也可以直接在 CMakeLists.txt 中加上 set(Ceres_DIR "包含 CeresConfig.cmake文件的绝对路径,一般编译后的文件夹中"),然后在 find_package(Ceres),CMake 就会自动的在这个路径下查找执行 CeresConfig.cmake 文件,之后这个 Ceres 库我们就可以使用了。即使多个版本,我们只要把上面 set 语句的路径部分替换一下就能使用不同版本 Ceres了。
注意:如果我们有多个 Ceres 编译好的源码版本,我们可以在 .cmake/packages/Ceres /xxx_filename 文件中修改为不同 Ceres 源码版本目录地址,这样就可以使用不同的 Ceres 版本了。
如何生成C++库的.cmake文件
为什么要生成.cmake文件:生成C++文件编译后的.cmake文件,便于被其它程序通过find_package()调用
如何生成:CMakeLists.txt 中都有 export(PACKAGE Sopus/Pangolin)
,然后 cmake 会自动将包含 SopusConfig.cmake 和 PangolinConfig.cmake 文件的路径分别放到 ./cmake/packages/Sophus/xxx_filename 和 .cmake/packages/Pangolin/xxx_filename,然后系统会自动找到。
这种方式其实我们可以推广到其他的库,比如 OpenCV 库,我们可以仅编译 OpenCV 的源码不安装。然后在 .cmake/packages/ 中建立 OpenCV 文件夹和一个任意名字的文件,里面写上 OpenCV 源码中包含 OpenCVConfig.cmake 文件的目录地址, 一般是 build 目录
注意:这种方式只适用于源码库在编译后提供了 xxxConfig.cmake 文件。这种方式属于 Config 模式。对于经常用到的 g2o 库,因为库的作者没有提供 G2OConfig.cmake 文件。所以没法用这种方式。只能用 Module 模式
find_package() 怎么找到库的头文件和库文件?
包含库的头文件和库文件的变量都在 Findxxx.cmake
或者 xxxConfig.cmake
中定义着,所以我们只要找到当中的**一种 **.cmake 文件即可。然后执行这个 .cmake 文件,我们就能得到库来使用。对于 CMake 而言,有两种查找方式。
(1)、Module 模式(查找Findxxx.cmake
文件)
CMake 会优先搜索 CMAKE_MODULE_PATH 指定的路径,然后搜索自己自带的 Modules 路径。所以一般来说,最常用就是在自己工程的 CMakeLists.txt 文件中更改 CMAKE_MODULE_PATH 这个变量值,或者把包含 Findxxx.cmake 文件的路径附加到这个变量中。之后就可以使用 find_package() 查找到对应的库。两种方式对应如下代码:
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake_modules/") # 后面这个路径就是在自己的工程目录中添加一个 cmake_modules 文件
# 一般推荐使用这个方式添加
LIST(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake_modules)
对于 CMake 本身自带的模块路径,我们没必要添加 Findxxx.cmake 文件到其中。只要利用好 CMake 为我们提供的 CMAKE_MODULE_PATH 这个变量即可。
(2)、Config 模式(查找xxxConfig.cmake
文件)
这个文件是库的作者提供的,或者你看明白库作者写的 CMakeLists.txt 文件后,修改生成 xxxConfig.cmake 文件),上面讲解的 Ceres 安装方式就是利用这种模式。CMake 会优先搜索 xxx_DIR 指定的路径,然后第二优先级才是搜索 /usr/lib/cmake/xxx/ 中对应的xxxConfig.cmake 文件。因此最常使用的做法,指定 xxx_DIR 到包含 xxxConfig.cmake 文件的路径。下面是最常用的命令。
set(xxx_DIR "dir") # dir 是包含 xxxConfig.cmake 文件的路径
find_package()
对于一些库,作者没有提供 xxxConfig.cmake 文件,只有 Findxxx.cmake 文件,那么我们只能用 Module 模式,然后推荐用 LIST(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake_modules)
,把当前工程用到的 .cmake 文件放在 cmake_modules 文件夹中。这样我们就可以顺利使用 find_package() 查找使用库了。
参考:
https://cslam.cn/archives/7dcb4bb9.html