mingw编译opencv动态链接库和静态链接库及使用方法

2023-02-13,,,,

前言

我一直不知道编译的过程以及cmake, make 这些工具是干什么的,所有抽时间研究了一下。
简单来说就是 cmake 是根据 CMakeLists.txt 用来生成 makefile文件的。而make 命令是根据 makefile 来生成可供使用的 动态连接库 或静态连接库的,以便你项目调用,make 命令在windows上与g++ gcc等命令在一个目录,不需要单独去下载,安装好 mingw 就是在其 bin 目录下,叫 mingw32-make.exe。

环境准备

mingw
opencv源码
cmake(最好下载最新版的,对新版的vc++识别更好)

opecv 项目如果你下载了vc++版本的也不需要重新下载源码了,因为解压后目录中包含源码,也是存放在 source目录下。
mingw安装好后将其中的 bin 目录设置到path环境变量中,以便后面cmake可以直接识别。

1.编译动态链接库

1.1 mingw 预配置

Where is the source code: 解压opencv项目后源码存放路径
Where to build the binaries: 存放构建的目录,可以是不存在的,因为点击configure会自动建立

设置好两个路径后可以直接点击 configure

选择MinGw makefiles,用默认本地编译器,然后点击下一步。

The CXX compiler identification is GNU 8.1.0
The C compiler identification is GNU 8.1.0
Detecting CXX compiler ABI info
Detecting CXX compiler ABI info - done
Check for working CXX compiler: C:/MinGW/bin/g++.exe - skipped
Detecting CXX compile features
Detecting CXX compile features - done
Detecting C compiler ABI info
Detecting C compiler ABI info - done
Check for working C compiler: C:/MinGW/bin/gcc.exe - skipped
Detecting C compile features
Detecting C compile features - done

开始检测环境,可以看到识别到了 g++ gcc等命令

1.2配置参数

参数很多,说几个可能用到的。

名字 作用
CMAKE_INSTALL_PREFIX 最终编译后存放的路径,此时这个目录可能是不存在的,只有最好执行make install命令才会建立
BUILD_opencv_python3 建立opencv python的第三方库,由于我这里不需要跟python相关的所以跟python相关我都取消勾选了
BUILD_opencv_world 将多个连接库合并成一个world链接库方便连接,建议勾选上
BUILD_SHARED_LIBS 是否建立dll, 如果不勾选就是建立静态库,默认勾选就是建立动态连接库

这里寻找选项有一个技巧,可以将

Grouped勾选上,方便寻找。
这里一步配置参数可以把 BUILD_opencv_world 选上,其余的几乎都不用动。

1.3生成makefile文件

点击 Generate 按钮, 等待生成。

这里可能会有一个问题Unable to open cache file for save. ....CMakeCache.txt
就是无法打开CMakeCache.txt 文件,我尝试过删除这个文件或者清除缓存,删不掉。
解决办法:1. 就是更换build目录,需要然后需要从新 configure, 修改配置和 generate,不推荐
2. 重启电脑,推荐

1.4 make编译项目

在 建立的目录 执行命令:

mingw32-make -j8

这里 -j8 是使用多线程来进行编译,也可以 -j16, 速度会比单独执行 mingw32-make 命令快很多。

1.5 安装

继续在编译后的目录执行命令:

mingw32-make install

这一步最终生成的文件就会在之前配置CMAKE_INSTALL_PREFIX 目录中。
这里注意 install 是命令,而不是参数,之前我目录名字就是 install,导致我以为这一步是指定一个目录来存放最终文件

\x64\mingw\bin 存放动态链接库 libopencv_world3414.dll (运行的时候使用), 在\x64\mingw\lib 存放静态链接库 libopencv_world3414.dll.a(编译链接时使用)。

1.6 使用opencv库

编写一个简单的调用摄像头的 opencv 程序:

#include <opencv2/opencv.hpp>
using namespace cv;
int main()
{
namedWindow("test");
VideoCapture capture(0, CAP_DSHOW);
while (true)
{
Mat src;
capture >> src;
int width = src.cols;
int heigh = src.rows; imshow("test", src);
if (waitKey(10) == 27) break; }
destroyAllWindows();
return 0; }

然后使用命令行进行编译:

g++ 文件名 -I 头文件目录 -L 连接库目录 -lopencv_world3414.dll

这里简单介绍一下参数作用:
-I :(注意这里是i的大写,不是L的小写)指定头文件目录 ,也就是 include 目录。
-L :指定链接库目录,与后面 -lopencv_world配合,意思是去-L 目录去查找 链接库。
-lopencv_world3414.dll: (这里是-L的小写,不是i的大写)使用这个链接库,文件名字其实是libopencv_world3414.dll.a 而使用的时候就需要去掉后面 .a 和前面的 lib 然后与 -l连接。所有链接库的使用方法都遵循这个模式。其实这个模式是去掉后缀名的内容,如果前面有 lib 那么去掉 lib 然后与-l链接,如果没有就直接与连接。

命令执行后会生成 a.exe 文件,而这个文件执行就会提示没有
libopencv_world3414.dll , 所以可以把 dll 文件放入与 a.exe 同级目录就可以了。或者一劳永逸的方法,将 dll 文件目录添加到 path 环境变量中,推荐这种方法。

2.编译静态链接库

编译静态链接库的方法和编译动态链接库步骤基本相同,只是在使用编译好的opencv静态链接库的时候有一些麻烦。后面也会详细说明如果使用 opencv静态链接库。

2.1 配置参数

1.2 配置参数 这步中将 BUILD_SHARED_LIBS 选项取消勾选,然后其余步骤与 编译动态连接库的步骤相同,当然我还是建立了world。

2.2 编译后内容介绍

\x64\mingw\staticlib 存放所有静态链接库,此时bin目录中就没有 dll 文件了,因为我们没有生成动态链接库,所有函数实现都在静态链接库中。细心你会发现 libopencv_world3414.a 会比 libopencv_world3414.dll.a 大很多,因为里面 多了函数实现,而 libopencv_world3414.dll.a作用是告诉程序去调用 libopencv_world3414.dll,其中没有真正的函数实现,函数真正实现全在dll文件中。

除了 libopencv_world3414.a 静态链接库之外还有:

很多其它这些链接库,而这些库在项目编译链接的时候也是需要使用的(如果不建立world会产生更多)。

2.3 使用opencv

程序还是上面那个程序,命令有一些不同(需要链接很多东西):

g++ test3.cpp -I 头文件目录 -L 链接库目录 -lopencv_world3414 -lzlib -lIlmImf -llibjasper -llibjpeg-turbo -llibpng -llibprotobuf -llibtiff -llibwebp -lquirc -lzlib

参数作用已经链接库调用写法前面已经介绍了。

这条命令下去应该会有几千个错误。因为静态链接还要使用很多windows内置的静态链接库才能编译成功。所有这里比较麻烦,需要安装vc++才会有这些链接库。我安装的是 visual studio 2019, 所有链接库在目录D:\Windows Kits\10\Lib\10.0.19041.0\um\x86,最终命令:

g++ test3.cpp -I D:\mingw_opencv_static\include -L D:\mingw_opencv_static\x64\mingw\staticlib -lopencv_world3414 -lzlib  -L "D:\Windows Kits\10\Lib\10.0.19041.0\um\x86" -lgdi32 -lComDlg32 -lOleAut32 -lOle32 -luuid   -lIlmImf -llibjasper -llibjpeg-turbo -llibpng -llibprotobuf -llibtiff -llibwebp -lquirc -lzlib

也就是添加了-lgdi32 -lComDlg32 -lOleAut32 -lOle32 -luuid 这些连接库,报出了一些警告但是还是可以编译成功的。

这里我最初找这些链接库是很麻烦的过程,看报错,列如:
undefined reference to __imp_CoCreateInstance 这个报错说明找不到 __imp_CoCreateInstance 这个函数,那么 Search all across Microsoft Docs 搜索这个函数,可以看到:

其存在于 Ole32.lib 这个静态连接库中,那么就在编译参数中加入这个静态链接库,所以我加入了 -lOle32

编译成功这个 a.exe 就可以脱离 dll 运行了。但是会比需要 动态链接库那个a.exe 的大很多,其实可以进一步精简:在源程序中引入的时候只引入你需要的头文件,然后不编译 opencv 库的时候不建立 world ,然后链接的时候就只引入你需要的链接库。

其它

如果你真是重头看到尾,我相信能理解很多东西。也能解决一些问题。

mingw编译opencv动态链接库和静态链接库及使用方法的相关教程结束。

《mingw编译opencv动态链接库和静态链接库及使用方法.doc》

下载本文的Word格式文档,以方便收藏与打印。