搞opencv的静态编译
- 静态编译就是说可以将你编译出来的可执行文件放到没有配置什么环境的电脑里,直接运行;
- 而动态编译则需要将用到的库文件放到相应位置,windows下将需要的库文件放到根目录即可,linux则需要放到系统路径中。
首先明确一点:想做自己写的程序的静态编译,例如写一个关于opencv的代码,首先需要将opencv库进行静态编译,网上有各种教程。windows上将opencv源码进行静态编译,然后通过对vs进行相应的简单配置,就可以生成静态编译的可执行文件。
linux上将opencv源码进行静态编译,注意一点:用cmake进行生成的时候,将CMAKE_INSTALL_PREFIX这个变量的值不要改动!默认为/usr/local!!!(血的教训)然后将其中的SHARE(动态编译)关掉。这样就可以进行生成编译了。
在执行自己cpp文件静态编译的时候,出现了很多的错误(捣鼓了很多天。。。都是泪)
CMakeLists的书写不难,只要将target_link_libraries()里面link你编译出来的opencv静态库就好了(不需要find_package)。但是会出现以下几类错误:通过笔者经历九九八十一难(可能是我太笨了。。。),我终于找到了解决方法:解决方式都一样,在target_link_libraries()里面最后添加相应的参数就好啦!!!
TARGET_LINK_LIBRARIES(... -lpthread -lm)
2.对_gzopen等的未定义引用(Undefined reference to _gzopen etc)
TARGET_LINK_LIBRARIES(... -lz)
3.对‘dlopen’未定义的引用
TARGET_LINK_LIBRARIES(... -ldl)
4.undefined reference to 'cv::String::deallocate()'
undefined reference to 'cv::String::allocate(unsigned long)'
将
find_package( OpenCV REQUIRED )
更改为
find_package( OpenCV 3 REQUIRED )
5.注意变量的大小写!
target_link_libraries( main ${OPenCV_LIBS})
变量大小写错,改为:
target_link_libraries( main ${OpenCV_LIBS})
终于没有那么多错误啦,静态编译成功啦!!!感恩!
笔者又想建立自己的静态库,并调用自己的静态库和opencv静态库
构建自己的静态库参考https://blog.csdn.net/Jeffxu_lib/article/details/85874144结果出现了链接问题。
解决了出现的问题后,得到的结论如下:
1. 自己的静态库无论调用其他的动态库还是静态库,只需要在源文件中include库的头文件就OK了
2. 要在调用该静态库的地方添加库引用,并设置路径。(若安装在/usr/local下,貌似可以不用添加路径也可以)
结论:其实静态库调用动态库或者静态库,只是在用到库方法的地方把该方法添加到LIB当中,真正使用的地方才会把这些库LINK起来生成可执行文件。(摘自:https://blog.csdn.net/wangjunhe/article/details/6690795?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-4.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-4.nonecase)
3,链接库具有依赖顺序,在link的时候必须按照顺序来写,要求被依赖的库放在依赖它的库后面,否则会出现“未定义的引用”的问题。
cmake中链接库的顺序是a依赖b,那么b放在a的后面。
例如进程test依赖a库,b库, a库又依赖b 库,那么顺序如下:
target_link_libraries(test a b)
上面的a,b的顺序不能变,只能按上面的先后顺序。如果去掉顺序的烦恼和痛苦,可以采用如下的写法:
target_link_libraries( test -Wl,--start-group b a -Wl,--end-group)
4,如何让有些“-l”链接静态库,而另一些链接共享库?
用“-Wl,-Bstatic
”指定链接静态库,使用“-Wl,-Bdynamic
”指定链接共享库,使用示例:
-Wl,-Bstatic -lmysqlclient_r -lssl -lcrypto -Wl,-Bdynamic -lrt -Wl,-Bdynamic -pthread -Wl,-Bstatic -lgtest
"-Wl"表示是传递给链接器ld的参数,而不是编译器gcc/g++的参数。
小白加油!只要不放弃,一定能成功!