







Ubuntu下安装OpenCV(三): CMake编译(下)
第七步: 将OpenCV共享库 (格式为lib*.so.*) 的路径添加进系统共享库缓存中
命令执行位置: /etc/ld.so.conf.d/下
命令行:
$ sudo touch <file name>.conf 创建文件
$ sudo gedit <file name>.conf 编辑文件, 并写入共享库所在位置<install_directory>/lib
$ sudo ldconfig 更新系统共享库缓存
注意:
1. <install_directory>是CMake编译时通过变量CMAKE_INSTALL_PREFIX设置的安装路径, 默认为/usr/local
2. ldconfig 的搜索目录复制
7.1 ldconfig
先来介绍 ldconfig命令的含义和作用 (http://manpages.ubuntu.com/manpages/bionic/en/man8/ldconfig.8.html)
共享库(Shared Library)也被称为动态库(Dynamic Library)或动态链接库,它会在可执行程序运行时被调用,在Windows系统下格式为*.dll,在Unix/Linux系统下格式为lib*.so.*,例如libopencv_plot.so,libopencv_photo.so.3.4.10等。
ldconfig是一个管理系统共享库的命令,它通过为共享库建立必要的链接和缓存,让计算机中的可执行程序可以成功调用这些库。
计算机中的共享库缓存文件为/etc/ld.so.cache,它存储了系统中所有的共享库名称及路径,这是一个二进制文件,没有办法直接读取,我们可以输入命令ldconfig -p来查看该文件的内容:

7.2 ldconfig的搜索目录
从7.1的定义可知,当我们运行可执行程序时,ldconfig命令会从一系列目录中搜索程序所需的共享库,如果找到了库,则程序可以成功调用该库,如果未找到,则程序报错。ldconfig的搜索目录包括系统信任的目录/lib和/usr/lib、还有/etc/ld.so.conf文件中的条目。
下面查看一下搜索目录中的内容,先看受信任的目录/lib和/usr/lib:

/usr/lib下保存着许多格式为lib*.so.*的共享库文件,如libgdal.so.20、libgjs.so.0等。/lib下虽然没有共享库,但是ld-linux.so.2是Linux的动态加载器(Dynamic Loader),它用于定位应用程序所需的动态库(共享库),并将其加载到内存中。
接下来看一看/etc/ld.so.conf的内容,该文件并没有记录共享库的具体路径。在我的计算机中,它只有一条语句include /etc/ld.so.conf.d/*.conf,其中include表示载入并运行文件内容,*.conf代表所有后缀为.conf的文件。所以这条语句的含义是读取/etc/ld.so.conf.d/目录下所有后缀为.conf的文件。

进入/etc/ld.so.conf.d/目录下,可以看到许多后缀为.conf的文件,使用cat命令查看其中两个文件libc.conf和x86_64-linux-gnu.conf的内容,发现.conf文件中记录的才是具体的共享库路径:

总结来说,ldconfig的搜索顺序是:检查/lib和/usr/lib目录-->读取/etc/ld.so.conf文件的内容-->根据include语句进入/etc/ld.so.conf.d 目录下挨个读取.conf文件-->前往.conf文件记录的路径下查找共享库。
7.3 操作步骤
(1) 新建.conf文件并写入共享库路径
第一步,我在/etc/ld.so.conf.d 文件夹下新建了一个名为opencv-3-4-10d.conf的文件,并写入debug版共享库的路径/usr/local/opencv-3-4-10-debug/lib。文件名没有特殊要求,但是一定要加.conf后缀,共享库的路径需要用户根据自己的系统来修改。
sudo touch <file name>命令可以新建指定名称的文件,sudo gedit <file name>命令可以编辑文件。

(2) 更新系统共享库路径缓存
保存好.conf文件之后可以使用cat命令查看一下路径的拼写是否正确,之后输入sudo ldconfig命令更新系统共享库的路径缓存即可

在一些教程中提到,用户可以将共享库的路径写入/etc/ld.so.conf文件中,这样ldconfig在读取该文件时 ,就可以直接进入路径下查找共享库。这种方法是可以的,不过我个人更喜欢单独创建一个文件来存放路径,感觉文件结构会更清晰一些。
第八步: 让pkg-config命令可以正确输出OpenCV算法头文件和共享库的信息
命令执行位置: pkg-config命令的搜索路径下, 下文使用的是/usr/lib/pkgconfig 目录
命令行:
$ sudo cp <install_directory>/lib/pkgconfig/opencv.pc /usr/lib/pkgconfig/<file name>.pc
注意:
1. <install_directory>是CMake编译时通过变量CMAKE_INSTALL_PREFIX设置的安装路径, 默认为/usr/local
2. pkg-config 的搜索路径
3. .pc文件的作用和内容
4. 检验pkg-config的设置是否生效复制
8.1 pkg-config
还是先来介绍一下pkg-config命令,这个命令用于获取某个已安装的库的编译信息(https://www.freedesktop.org/wiki/Software/pkg-config/)
当我们在使用g++命令执行编译任务时,编译用到的头文件和库文件路径都需要写入命令行中,如果链接的库太多,命令行就会变得很长。pkg-config可以帮助我们使用简单的语句输出一系列头文件和库文件的路径信息。
pkg-config命令后可以添加很多选项,命令行中输入pkg-config -h可以查看所有可用的选项。常用的选项有--cflags、--libs和--modversion。 --cflags会输出预处理器和编译器选项(也就是头文件的名称和路径),--libs会输出链接器选项(即库文件的名称和路径),--modversion可以输出版本号:
8.2 .pc文件
那么pkg-config是如何获取已安装库的信息呢?答案是从后缀为.pc的文件中读取(定义来自$man pkg-config)
.pc文件记录了库的各种信息,包括库的版本、编译模式、头文件路径、库文件路径等。这个文件一般是由第三方库提供的,用户也可以自己来编写。
OpenCV作为第三方库,就为我们提供了.pc文件,在2.x和3.x版本中名为opencv.pc,在4.x版本中名为opencv4.pc。
在之前编译的过程中,.pc文件一共生成了两次。第一次生成是在make编译这一步:

该文件被保存在构建目录下的unix-install文件夹中:

第二次生成是在make install这一步:


两个.pc文件是相同的,使用cat命令来查看一下具体的文件内容:

8.3 pkg-config的搜索路径
仅仅生成了.pc文件还是不够的,想要pkg-config成功输出.pc文件的内容,就需要将该文件放置在pkg-config的搜索路径下(定义来自$man pkg-config)
定义中只列举了一部分pkg-config的搜索路径,在命令行输入pkg-config --variable pc_path pkg-config可以查看自己系统中pkg-config的全部搜索路径,路径与路径之间使用冒号分隔:


8.4 操作步骤
这一步的步骤非常简单,将opencv.pc复制到pkg-config的任意一个搜索路径中即可,我选择的目录是/usr/lib/pkgconfig,用户可以选择自己喜欢的目录。
使用cp命令将OpenCV生成的opencv.pc文件复制到/usr/lib/pkgconfig目录下,顺便给文件改名为opencv-3-4-10d.pc。前文提到过,OpenCV2.x和3.x生成的.pc文件都叫opencv.pc,为了区分不同版本和编译模式生成的文件,我在这里修改了文件名。

复制完成之后,可以使用pkg-config命令来验证一下配置是否成功。输入pkg-config --modversion <package name>、pkg-config --cflags <package name>和pkg-config --libs <package name>进行测试,<package name>是.pc文件去掉后缀的名称,这里是opencv-3-4-10d,记得不要写成opencv了。

8.5 PKG_CONFIG_PATH
It will additionally look in the colon-separated (on Windows, semicolon-separated) list of directories specified by the PKG_CONFIG_PATH environment variable.


第九步: 更新系统中的文件名数据库
命令执行位置: 无要求
命令行:
$ sudo updatedb
注意:
1. locate命令复制
最后,运行一个很简单的命令sudo updatedb来更新系统中的文件名数据库。

The updatedb program updates the file name database used by the locate program. The file name database contains lists of files that were in particular directory trees when the databases were last updated.

第十步: 测试核心算法和额外算法
命令执行位置: <opencv_source_directory>/samples/cpp/
命令行:
$ sudo g++ -o <executable program name> <source code file> `pkg-config --cflags --libs <.pc filename>`
$ sudo ./<executable program name>
注意:
1. 可以新建源代码文件进行测试, 也可以使用OpenCV自带的样例程序复制



10.2 额外算法
接下来测试额外算法模块,我选择的是samples/cpp/tutorial_code/xfeatures2D目录下的程序。该文件夹下只有一个源文件LATCH_match.cpp,用于实现LATCH匹配算法。
输入sudo g++ -o LATCH_match LATCH_match.cpp `pkg-config --cflags --libs opencv-3-4-10d`来编译源代码,我将生成的可执行程序命名为LATCH_math;之后使用sudo ./LATCH_match命令执行程序即可。



以上就是Debug版本的OpenCV安装与配置的最后一节了 这一篇主要是在做编译后的一些配置任务,虽然步骤很简单但是很重要。每一个步骤也有多种方法可以选择。



