背景
最近的一个工作任务是将之前在联咏平台上做的一个人脸识别的项目移植过去。之前这个项目主要是做的,移植的事情自然落到我身上了。组里也没人搞过瑞芯微的,开始踩坑淌水。
交叉编译工具
问了公司一圈人也没一个文档告诉我瑞芯微交叉编译的环境在哪儿,只有自己搭建一个了。
交叉编译工具链下载地址:
配置 cmake toolchain,命名为toolchain_RK.cmake
# cmake_minimum_required (VERSION 3.12)
# PLATEFORM_COMPILER_TOOL配置成自己交叉编译工具的目录
set(PLATEFORM_COMPILER_TOOL "/opt/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-")
# this one is important
SET(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
#this one not so much
SET(CMAKE_SYSTEM_VERSION 1)
# where is the target environment
SET(CMAKE_FIND_ROOT_PATH /opt/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/)
# specify the cross compiler
set(CMAKE_C_COMPILER "${PLATEFORM_COMPILER_TOOL}gcc")
set(CMAKE_CXX_COMPILER "${PLATEFORM_COMPILER_TOOL}g++")
# # search for programs in the build host directories
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# # for libraries and headers in the target directories
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
编译opencv
从opencv 官网上下载opencv的源码进行编译。编译很简单
mkdir build_rk1109
cd build_rk1109
cmake .. -DCMAKE_TOOLCHAIN_FILE=../toolchain_RK.cmake
然后愉快得等待build完成,编译完成之后兴高采烈地开始进行测试。熟练地写上测试代码demo.cpp
#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui/highgui.hpp>
int main()
{
cv::Mat img;
img = cv::imread("./1.jpg");
std::cout << img << std::endl;
}
然后写成CMakeList.txt
cmake_minimum_required(VERSION 3.1)
project(demo)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(OPENCV_INCLUDE_DIRS /home/lc/Desktop/yutao/opencv/include)
set(OPENCV_LINK_LIBS /home/lc/Desktop/yutao/opencv/lib)
link_directories(${OPENCV_LINK_LIBS})
include_directories(${OPENCV_INCLUDE_DIRS})
add_executable(demo demo.cpp)
target_link_libraries(demo
opencv_core
opencv_highgui
opencv_imgproc
opencv_highgui
)
然后就报错了。
问题分析和排查
现象1:
这是在链接libopencv_core.so的时候报的这么个错误,无非就是找不到这个reference。网上google了半天,都也试了各种参数都不work。最后在这两篇博客中找到了原因
error: undefined symbol: std::__cxx11::basic_string和std::__1::basic_string_三级狗的博客-CSDN博客undefined symbol: cv::imwrite(cv::String const&, cv::_InputArray const&, std::__1::vector<int, std::__1::allocator > const&)https://blog.csdn.net/Three_dog/article/details/104701644原因就是gcc5以及以后的版本,将std::string和std::list重写,std::list变为std::__cxx11::list<int>,std::string在c++03库是std::basic_string<char>,而在c++11中变为了std::__cxx11::basic_string<char>。而为了在编译的时候兼容旧版本(链接阶段),可在编译的时候启动_GLIBCXX_USE_CXX11_ABI 宏指定具体链接的库。
于是照着博主的命令看了一眼自己编译出来的库
nm -D libopencv_core.so | c++filt | grep compare
嗯,确实是std::basic_string, 别人要的是std::__cxx11::basic_string,那找不到就正常了。所以解决办法就是重新编译opencv了,编译选项加上-std=c++11
现象2:
重新编译完之后,心想现在总能顺利编译了吧,结果还是报错了
怎么又找不到了? 网上有说加-D_GLIBCXX_USE_CXX11_ABI=1参数的。我试试看吧.
还是一样的报错,那换成0呢?
它又这样报错了。最后还是找到了问题原因
新版本的opencv 把读取从链接库libopencv_highgui中剥离出来多了一个libopencv_imgcodecs出来。因此在使用新版本的opencv的时候需要把这个连接库也加上。
把libopencv_imgcodecs链上去之后,终于编译成功了!上板运行也成功了。
总结
本文介绍了本人在瑞芯微rv1109平台上交叉编译opencv的过程,下一步会尝试使用瑞芯微SDK进行推理,遇到问题将继续做记录
文章出处登录后可见!