自己编译 ARM 版 opencv-mobile
自己编译 ARM 版 opencv-mobile 解决编译器版本导致的 undefined reference to std::__cxx11::basic_stringstream
问题
起因
因项目需要在 arm 版中进行简单的图形运算,于是打算直接用 opencv-mobile 仓库预编译好的 opencv-mobile-4.5.4-armlinux.zip。但果然因为生产环境依赖的编译器版本太旧,在编译过程遇到了因为 ABI 接口导致的错误:
undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
undefined reference to `std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> > const&)
...
尝试直接使用 -D _GLIBCXX_USE_CXX11_ABI=0,无效
搜索一圈无果,(#20 #25 #27)
于是决定自己编译一遍,解决问题,顺便编写这个文档,方便后人查阅。
arm-linux-gnueabihf 编译步骤
-
前置步骤,在 Linux 中安装好 CMake,arm-linux-gnueabihf 工具链
-
下载 opencv-mobile 源码
https://github.com/nihui/opencv-mobile/archive/refs/tags/v14.zip
此处使用 v14 版本,使用其他版本可能需要在后续的操作中修改部分命令参数 -
进入 clone 所在文件夹,运行以下命令
该命令会 A:下载 opencv 4.5.4; B:解压到 opencv-4.5.4 文件夹内; C:进入该文件夹.
wget -q https://github.com/opencv/opencv/archive/4.5.4.zip -O opencv-4.5.4.zip
unzip -q opencv-4.5.4.zip
cd opencv-4.5.4
此时,文件夹结构如图所示:
-
编译
-
可选配置步骤,下面的指令都在
opencv-4.5.4
文件夹中执行-
strip zlib dependency and use stb-based highgui implementation (optional)
patch -p1 -i ../opencv-4.5.4-no-zlib.patch truncate -s 0 cmake/OpenCVFindLibsGrfmt.cmake rm -rf modules/gapi rm -rf modules/highgui cp -r ../highgui modules/
-
patch opencv source for no-rtti build (optional)
patch -p1 -i ../opencv-4.5.4-no-rtti.patch
-
apply your opencv options to opencv4_cmake_options.txt
opencv4_cmake_options.txt 文件在
/opencv-mobile/opencv4_cmake_options.txt
-
-
依次执行指令进行编译
mkdir build-arm-linux-gnueabihf && cd build-arm-linux-gnueabihf cmake -DCMAKE_TOOLCHAIN_FILE=../../toolchains/arm-linux-gnueabihf.toolchain.cmake \ -DCMAKE_C_FLAGS="-fno-rtti -fno-exceptions" -DCMAKE_CXX_FLAGS="-fno-rtti -fno-exceptions" \ -DCMAKE_INSTALL_PREFIX=install -DCMAKE_BUILD_TYPE=Release `cat ../../opencv4_cmake_options.txt` -DBUILD_opencv_world=OFF .. cmake --build . -j 2 cmake --build . --target install
-
-
编译完成
- 输出位于
./build-arm-linux-gnueabihf/install 中
- 把 install 移动到合适位置,如
/thirdpart/opencv4.5.4/my-gnueabihf/
- 输出位于
-
使用编译好的库
main.cpp
#include <opencv2/opencv.hpp> #include <iostream> int main() { cv::Mat mat = cv::Mat::zeros(256,256, CV_8UC1); { cv::rectangle(mat, cv::Rect(40, 45, 51, 65), cv::Scalar(255), -1, cv::LINE_8, 0);//绘制填充矩形 cv::rectangle(mat, cv::Rect(180, 180, 85, 21), cv::Scalar(255), -1, cv::LINE_8, 0);//绘制填充矩形 std::cout << "mat.rows = " << mat.rows << std::endl; std::cout << "mat.cols = " << mat.cols << std::endl; } return 0; }
demo makefile
# 改成你的路径 OPENCV_DIR := /thirdpart/opencv4.5.4/my-gnueabihf/ THIRD_PART_INCLUDE := -I$(OPENCV_DIR)include/opencv4 -I$(OPENCV_DIR)include/opencv4/opencv2 THIRD_PART_LIBRARY := $(OPENCV_DIR)lib/libopencv_highgui.a $(OPENCV_DIR)lib/libopencv_features2d.a $(OPENCV_DIR)lib/libopencv_imgproc.a $(OPENCV_DIR)lib/libopencv_photo.a $(OPENCV_DIR)lib/libopencv_video.a $(OPENCV_DIR)lib/libopencv_core.a TARGET = Test_OpenCV_Mobile START: @echo START rm -rf $(TARGET) arm-linux-gnueabihf-g++ -O2 -std=c++11 -lpthread -fopenmp -ldl $(CFLAGS) $(THIRD_PART_INCLUDE) -o $(TARGET) ./main.cpp $(THIRD_PART_LIBRARY) .PHONY:clean clean: rm -rf $(BINDIR)
demo CMakeLists.txt
cmake_minimum_required(VERSION 3.20) set (ARM_LINUX_GCC_PATH /usr/local/arm/gcc-linaro-5.3.1-2016.05-i686_arm-linux-gnueabihf/bin/) # 改成你的路径 set (CMAKE_C_COMPILER ${ARM_LINUX_GCC_PATH}arm-linux-gnueabihf-gcc) set (CMAKE_CXX_COMPILER ${ARM_LINUX_GCC_PATH}arm-linux-gnueabihf-g++) project(Test_OpenCV_Mobile) set(CMAKE_CXX_STANDARD 11) set(OpenCV_DIR "/thirdpart/opencv4.5.4/my-gnueabihf/lib/cmake/opencv4") # 改成你的路径 find_package(OpenCV REQUIRED) FIND_PACKAGE(OpenMP REQUIRED) add_executable(Test_OpenCV_Mobile main.cpp) target_link_libraries(Test_OpenCV_Mobile pthread) target_link_libraries(Test_OpenCV_Mobile dl) target_link_libraries(Test_OpenCV_Mobile -fopenmp) target_link_libraries(Test_OpenCV_Mobile ${OpenCV_LIBS})
运行结果
最后在末尾推荐使用,PRemoteM 来打开 SSH、SFTP、RDP 远程会话。
作者:VShawn
出处:http://www.cnblogs.com/singlex/
本文版权归作者所有,欢迎转载,但未经博客作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。