自己编译 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 编译步骤

  1. 前置步骤,在 Linux 中安装好 CMake,arm-linux-gnueabihf 工具链

  2. 下载 opencv-mobile 源码
    https://github.com/nihui/opencv-mobile/archive/refs/tags/v14.zip
    此处使用 v14 版本,使用其他版本可能需要在后续的操作中修改部分命令参数

  3. 进入 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

此时,文件夹结构如图所示:
image-20220518152817266

  1. 编译

    1. 可选配置步骤,下面的指令都在 opencv-4.5.4 文件夹中执行

      1. 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/
        
      2. patch opencv source for no-rtti build (optional)

        patch -p1 -i ../opencv-4.5.4-no-rtti.patch
        
      3. apply your opencv options to opencv4_cmake_options.txt

        opencv4_cmake_options.txt 文件在 /opencv-mobile/opencv4_cmake_options.txt

    2. 依次执行指令进行编译

      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
      
  2. 编译完成

    1. 输出位于 ./build-arm-linux-gnueabihf/install 中
    2. 把 install 移动到合适位置,如 /thirdpart/opencv4.5.4/my-gnueabihf/
  3. 使用编译好的库

    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)
    

    image-20220518155708643

    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})
    

    image-20220518160849421

    运行结果
    image-20220518154610943


最后在末尾推荐使用,PRemoteM 来打开 SSH、SFTP、RDP 远程会话。

posted @ 2022-05-18 16:37  V·Shawn  阅读(1441)  评论(0编辑  收藏  举报