前言

我一直不知道编译的过程以及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. 跟羽夏学 Ghidra ——初识

    写在前面   此系列是本人一个字一个字码出来的,包括示例和实验截图.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇文章 ...

  2. 使用脚本在FTP上传、下载文件

    由于最近勒索病毒变种又一次爆发,公司内部封锁了TCP 445端口.导致原来通过文件共享的方式上传下载的计划任务无法执行.所以,我开设了FTP服务器来完成这个工作. 关于如何建立FTP服务器,请看这里 ...

  3. flannel跨主网络通信方案(UDP、VXLAN、HOST-GW)详解

  4. Linux实例常用内核网络参数介绍与常见问题处理---重要

    文章转载自:https://help.aliyun.com/knowledge_detail/41334.html 本文主要介绍如下几点内容,您可以根据实际需要选择. 查看和修改Linux实例内核参数 ...

  5. 15_abstract,static,final

    一. abstract 1. 抽象类 被abstract修饰的类,称为抽象类 抽象类意为不够完整的类.不够具体的类 抽象类对象无法独立存在,即不能new对象,但可以声明引用 作用: 可被子类继承,提供 ...

  6. vue基础之MV*和它们之间的不同

    vue中的设计思想 vue中的设计思想主要是MV*模式,由最早的MVC(model-view-controller)框架,到后面的MVP(model-view-presenter),甚至到最后的MVV ...

  7. 移动端touch拖动事件和click事件冲突问题解决

    通过一个悬浮球交互功能的案例来阐述问题,以及解决办法. 实现效果 类似微信里的悬浮窗效果,苹果手机的悬浮球功能效果 可以点击拖动,然后吸附在窗口边缘 点击悬浮球,可以跳转界面,或者更改悬浮球的形态 准 ...

  8. aardio + PHP 可视化快速开发独立 EXE 桌面程序

    aardio 支持与很多编程语言混合开发.网络上大家分享的 aardio + Python 混合开发的文章很多,aardio + PHP 的文章却很少. 其实 aardio 与 PHP 混合开发是真的 ...

  9. mac通过docker一键部署Nexus3

    目录 mac通过docker一键部署Nexus3 一.前言 二.系统配置 三.安装步骤 1.Dockerhub查看镜像地址 2.一键安装 2.1.克隆脚本 2.2.安装程序 2.2.1.程序安装详情 ...

  10. aws上传文件、删除文件、图像识别

    目录 aws的上传.删除s3文件以及图像识别文字功能 准备工作 安装aws cli 初始化配置AWS CLI s3存储桶开通 图像识别文字功能开通 aws的sdk 上传文件 方法一 方法二 删除文件 ...