前言

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

环境准备

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动态链接库和静态链接库及使用方法的更多相关文章

  1. [转载]GCC 编译使用动态链接库和静态链接库--及先后顺序----及环境变量设置总结

    来自http://blog.csdn.net/benpaobagzb/article/details/51364005 GCC 编译使用动态链接库和静态链接库 1 库的分类 根据链接时期的不同,库又有 ...

  2. GCC 编译使用动态链接库和静态链接库

    1 库的分类 根据链接时期的不同,库又有静态库和动态库之分. 静态库是在链接阶段被链接的(好像是废话,但事实就是这样),所以生成的可执行文件就不受库的影响了,即使库被删除了,程序依然可以成功运行. 有 ...

  3. GCC 编译使用动态链接库和静态链接库的方法

    1 库的分类 依据链接时期的不同,库又有静态库和动态库之分. 静态库是在链接阶段被链接的.所以生成的可执行文件就不受库的影响了.即使库被删除了,程序依旧能够成功执行. 有别于静态库,动态库的链接是在程 ...

  4. 【转】gcc 编译使用动态链接库和静态链接库

    1 库的分类 根据链接时期的不同,库又有静态库和动态库之分. 静态库是在链接阶段被链接的(好像是废话,但事实就是这样),所以生成的可执行文件就不受库的影响了,即使库被删除了,程序依然可以成功运行. 有 ...

  5. Linux下动态链接库和静态链接库

    第一部分:编译过程 先了解一下linux下C代码的编译过程,C代码的编译,一般分成四个阶段,包括:预编译,编译,汇编和链接,这四个阶段的分工是 预处理过程,负责头文件展开,宏替换,条件编译的选择,删除 ...

  6. Qt 共享库(动态链接库)和静态链接库的创建及调用

    前言: 编译器 Qt Creator, 系统环境 win7 64 位 1.创建共享库: 新建文件或项目->选择 Library 和 c++ 库->选择共享库->下一步(工程名为 sh ...

  7. GCC编译过程与动态链接库和静态链接库

    1. 库的介绍 库是写好的现有的,成熟的,可以复用的代码.现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常. 本质上来说库是一种可执行代码的二进制形式,可 ...

  8. VS2010编译Boost 1.57 静态链接库

    http://www.cnblogs.com/cuish/p/4175491.html 0.前提 Boost库版本 1.57.0 下载地址 http://www.boost.org/users/his ...

  9. 利用GCC编译器生成动态链接库和静态链接库

    转载请标明:http://www.cnblogs.com/winifred-tang94/ 1.编译过程 gcc –fPIC –c xxx.c 其中-fPIC是通知gcc编译器产生位置独立的目标代码. ...

  10. Windows 下动态链接库和静态链接库

    1.静态链接库:就是在编译的时候把库中代码复制进工程中,导致工程变大,但是速度快. 缺点在于一套代码可能在内存中有多份拷贝,占用内存. 2.动态链接库:库由windos api加载库代码,内存中只有一 ...

随机推荐

  1. **手把手教你安装 Anaconda + Tensor flow+Pycharm**

    手把手教你安装 Anaconda + Tensor flow+Pycharm 这篇博文主要讲一下自己安装Anaconda + Tensor flow + Pycharm 的一个过程. 1. ANACO ...

  2. 微信公众号商城、小程序商城、H5商城 实例 前后端源码

    CRMEB客户管理+电商营销系统  https://gitee.com/ZhongBangKeJi/CRMEB 演示站后台: http://demo.crmeb.net/admin 账号:demo 密 ...

  3. Kubernetes DevOps: Jenkins

    提到基于 Kubernete 的CI/CD,可以使用的工具有很多,比如 Jenkins.Gitlab CI 以及新兴的 drone 之类的,我们这里会使用大家最为熟悉的 Jenkins 来做 CI/C ...

  4. filebeat直接给es传输日志,自定义索引名

    ElasticStack从2019年1月29日的6.6.0版本的开始,引入了索引生命周期管理的功能,新版本的Filebeat则默认的配置开启了ILM,导致索引的命名规则被ILM策略控制. 加上这个配置 ...

  5. 使用Docker搭建Fluentd

    说明: 1.该镜像内默认配置文件路径是/fluentd/etc/fluent.conf 2.该镜像默认启用tcp的5140和24224端口 3.镜像dockerhub地址:https://hub.do ...

  6. c#-03关于类和继承的基本知识

    一.类继承 通过类继承可以定义一个新类,新类纳入一个已经声明的类进行扩展 已经存在的类叫做基类,而通过继承出的类叫做派生类,派生类的组成为: 本身声明中的成员 基类的成员 派生类无法删除基类成员,但可 ...

  7. 离线安装chrome浏览器的postman插件

    最近开始研究webapi相关的东西,看到chrome浏览器的有个postman插件挺好用的,但是安装包下载下来以后会出现这种情况,这时候我们可以把crx后缀的改成zip格式的然后解压,然后选择开发者模 ...

  8. Centos7使用sendEmail-v1.56发送邮件

    Centos7使用sendEmail-v1.56发送邮件 注意:Centos7默认使用perl5.16,而sendEmail-v.1.56要求使用perl5.10.否则会报以下错误.所以需要下载并安装 ...

  9. uoj349【WC2018】即时战略

    题目链接 WC出了点意外滚粗了,来补补题. \(O(n^2)\)的时间复杂度,\(O(nlogn)\)的询问次数应该还是比较好想的,每次要打通到x的路径,对当前已知的树不断的找重心并询问在重心的哪颗子 ...

  10. iframe的简单使用

    看人家写的真的是摸不着头脑.自己写.还是清楚 局部数据的刷新:可以使用ajax.这里只是简单的演示 只作:例子使用.简单演示页面跳转 a标签中target属性和iframe中的name对应.相当于将该 ...