C++源文件通过CMake编译安装成库文件供其它程序使用,核心是如何通过find_package()找到其他库

调用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

你可能感兴趣的:(C++源文件通过CMake编译安装成库文件供其它程序使用,核心是如何通过find_package()找到其他库)