记录了这两天搭建开发环境碰到的问题,我PC的开发环境是ubuntu18.04,目标平台是rk3399+ubuntu
一、QT
1、在pc上安装qt creator,这个网上有很多资料也很简单(期间参考了c.biancheng.net/view/3851.html),具体如下。
1)下载安装文件,官网下载可能比较慢,可以在国内镜像下载。(我用的网址https://mirrors.tuna.tsinghua.edu.cn/qt/official_releases/qt/5.12/5.12.2/)
2)执行下载下来的qt-opensource-linux-x64-5.12.2.run即可跳出安装界面。
但有个需要注意的是默认情况下安装时会提示要注册,可以现将PC网络断掉后再执行该程序,这样可以跳过注册的界面直接开始安装。
2、配置qt creator的编译环境。qt creator在夸平台编译上做的很方便。如果要编译某个平台下的程序,只需要添加一个该平台的编译环境(主要需要添加编译工具gcc/g++,qmake就可以了),然后在构建项目时选择该环境就可以了。
1)点击qt creator左侧菜单中的Manage Kits即可弹出添加和修改编译环境的界面,默认系统会自己检测和生成一个pc上的编译环境Kits(我电脑上显示为取名为Desktp Qt 5.12.2 64bit)
2)点击该窗口右边的添加按钮,可以新增加一个,我增加的名称为rk3399,添加新Kits关键是要选择下面的“编译器”和“Qt 版本”,sysroot也最好选上,这样库和头文件的路径在编译的时候就可以自己找到了。“编译器”和“Qt 版本”需要在该窗口的另外两个界面“编译器”和“Qt Versions”界面进行添加后才能选择
3)编译器添加时直接选择sdk中相应的交叉编译工具即可
4)“Qt Versions”添加实际上是需要选择一个qmake,我走过弯路,开始选择的是在板子上通过apt install安装qt5-default后下载下来的qmake,一直提示报错。实际上需要选择在pc上用交叉编译工具编译生成的qmake才可以。我通过rk3399 sdk中的buildroot编译出qmake(编译方法见后面qt编译部分),选择这个ok
5)编译成功后运行程序报/usr/bin/ld: cannot find -lGL错误,执行: sudo apt-get install libgl1-mesa-dev 后ok
二、opencv
1、开始本来也想直接用sdk中的buildroot编译出来比较省事,但sdk的buildroot编译出来的版本为3.x的,我们需要用最新版本4.5.x的。我还是想利用buildroot写好的配置来编译,所以我就在网上下了一个最新的buildroot(https://buildroot.org/download.html)包解压看里面的package目录下也只有opencv3目录,没有opencv4,这样就只有自己来下载代码编译了。
2、在网上下载opencv-4.5.1.tar.gz和opencv_contrib-4.5.1.zip两个包(官网下载很慢,我是找了一个国内人下载后共享出来的链接下载的),opencv_contrib-4.5.1.zip包含和一些开源的功能模块代码。我的理解为这个包类似于插件或者是opencv功能的一个丰富。
3、解压opencv-4.5.1.tar.gz和opencv_contrib-4.5.1.zip,将解压后的opencv_contrib-4.5.1拷贝到opencv-4.5.1目录,这样我们代码下载和解压就完成了
4、编译。如果为pc编译比较简单,直接创建一个build目录或者build_x86目录,然后在该目录下执行cmake .. 再进行make和make install就编译完成了
5、为目标板子rk3399交叉编译。
1)创建目录build_rk3399
2)在该目录下执行如下命令:(注意cmake 一系列参数后的 .. ,表示源代码路径,这里是指上级目录)
cmake -D CMAKE_BUILD_TYPR=RELEASE -D CMAKE_INSTALL_PREFIX=./usr/local -D WITH_CUDA=ON -D ENABLE_FAST_MATH=1 -D WITH_CUBLAS=1 -D BUILD_EXAMPLES=ON -D CMAKE_C_COMPILER=~/edisk/work/rk3399_buildroot/rk3399_linux_release_v2.5.1_20210301/buildroot/output/host/bin/aarch64-linux-gcc -D CMAKE_CXX_COMPILER=~/edisk/work/rk3399_buildroot/rk3399_linux_release_v2.5.1_20210301/buildroot/output/host/bin/aarch64-linux-g++ ..
3)执行make -j8 开始编译,我在编译过程中出现了几次报错,具体如下:
a)提示下面的错误。解决办法为在应用程序的项目文件 xxxx.pro中增加LIBS +=-lopencv_flann 解决
warning: libopencv_flann.so.4.5, needed by /home/miaozhihua/edisk/work/opensource/opencv4_arm/opencv-4.5.1/build_rk3399/usr/local/lib/libopencv_features2d.so, not found (try using -rpath or -rpath-link)
libopencv_calib3d.so: undefined reference to `cv::flann::Index::~Index()'
libopencv_features2d.so: undefined reference to `cv::flann::IndexParams::IndexParams()'
libopencv_features2d.so: undefined reference to `cv::flann::IndexParams::~IndexParams()'
b)提示和png相关的几个函数引用找不到,屏蔽3rdparty/libpng/pngpriv.h中的如下定义就可以了
//miaozh mask
/*
# if (defined(__ARM_NEON__) || defined(__ARM_NEON)) && \
defined(PNG_ALIGNED_MEMORY_SUPPORTED)
# define PNG_ARM_NEON_OPT 2
# else
# define PNG_ARM_NEON_OPT 0
# endif
*/
3)编译过程中报如下错误:
aarch64-linux-gnu/bin/ld: 找不到 -lgthread-2.0
aarch64-linux-gnu/bin/ld: 找不到 -lglib-2.0
在CMakeLists.txt中添加buildroot sdk编译出的lib所在目录就可以了,如下:
link_directories("/xxx/rk3399_linux_release/buildroot/output/rockchip_rk3399/target/usr/lib/")
4)在包含了opencv的相关头文件,比如下面这些文件后,编译的时候还是提示Mat类没有定义,最后发现代码中还需要添加using namespace cv;或者用cv:Mat才可以
#include
#include
#include
#include
#include "opencv2/imgproc/types_c.h"
#include
#include
三、qt库编译方法记录。
1)下载代码 http://download.qt.io/archive/qt/5.12/5.12.2/ , 下载 qt-everywhere-src-5.12.2.tar.xz
2)解压后修改qmake.conf,具体文件路径在:mkspecs/linux-aarch64-gnu-g++/qmake.conf,在里面修改相关编译工具就可以了,具体如下:
# modifications to g++.conf
QMAKE_CC = /opt/rk3399/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc
QMAKE_CXX = /opt/rk3399/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-g++
QMAKE_LINK = /opt/rk3399/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-g++
QMAKE_LINK_SHLIB = /opt/rk3399/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-g++
# modifications to linux.conf
QMAKE_AR = /opt/rk3399/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-ar cqs
QMAKE_OBJCOPY = /opt/rk3399/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-objcopy
QMAKE_NM = /opt/rk3399/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-nm -P
QMAKE_STRIP = /opt/rk3399/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-strip
3)配置,我用的配置命令和选项如下:
./configure \
-prefix _install \
-xplatform linux-aarch64-gnu-g++ \
-confirm-license \
-opensource \
-release \
-make libs \
-pch \
-qt-libjpeg \
-qt-libpng \
-qt-zlib \
-no-opengl \
-recheck-all
4)执行make -j8 && make install 后上面qtcreator添加KITS的QT versions需要的qmake位于安装目录_install/bin/qmake
5)但上面的库没有带opengl,如果不加-no-opengl配置会报如下错误,后续还是需要将opengl打开的,不然显示效率比较低,可以在网上搜索QMAKE_LIBS_OPENGL rk3399找相关解决方案尝试
ERROR: The OpenGL functionality tests failed!
You might need to modify the include and library search paths by editing QMAKE_INCDIR_OPENGL[_ES2],
QMAKE_LIBDIR_OPENGL[_ES2] and QMAKE_LIBS_OPENGL[_ES2] in the mkspec for your platform.
6)理论上需要将_install/lib和_install/plugins/platforms/下的相关文件拷贝到目标板子的文件系统中的。这样用qtcreator编译出来的应用程序就可以在板子上运行了。但我这里碰到了下面的问题:
a)将上面编译出来的qt库拷贝到板子上运行时提示如下错误:(该问题目前还未解决)
qt.qpa.plugin: Could not find the Qt platform plugin “xcb“ in ““
尝试解决:增加-xcb配置后重新编译,具体配置如下
./configure \
-prefix _install \
-xplatform linux-aarch64-gnu-g++ \
-confirm-license \
-opensource \
-release \
-make libs \
-pch \
-qt-libjpeg \
-qt-libpng \
-qt-zlib \
-xkbcommon \
-qt-xcb \
-recheck-all
结果在编译的时候报下面的错误,看起来xkbcommon和xcb库要单独编译后给配置文件指定库和头文件的路径后才能配置成功。因为没有找到这两个依赖库的源码,所以没办法进行下去了。
ERROR: Feature 'xkbcommon' was enabled, but the pre-condition 'libs.xkbcommon' failed.
ERROR: Feature 'xcb' was enabled, but the pre-condition 'features.thread && features.xkbcommon && libs.xcb' failed.
ERROR: The OpenGL functionality tests failed!
You might need to modify the include and library search paths by editing QMAKE_INCDIR_OPENGL[_ES2],
QMAKE_LIBDIR_OPENGL[_ES2] and QMAKE_LIBS_OPENGL[_ES2] in the mkspec for your platform.
b)然后我又在buildroot中编译了一个qt的库,将buildroot中编译出的qt库拷贝到板子上运行程序时提示如下错误:(该问题目前还未解决)
error while loading shared libraries: libpcre2-16.so.0: cannot open shared object file: No such file or directory
将buildroot中编译出的libpcre2相关库文件拷贝到板子上后(sudo cp target/usr/lib/libpcre2-* /usr/lib/ -a)报如下错误
/lib/aarch64-linux-gnu/libm.so.6: version `GLIBC_2.29' not found (required by /usr/lib/libQt5Widgets.so.5)
最后发现是rk3399 sdk中buildroot所用的交叉编译工具和其ubuntu中用的编译工具版本不一致。板子ubuntu上的libm.so.6链接的是libm-2.27.so文件。而buildroot中用的是2.29版本,所以用buildroot编译出的程序需要2.29的版本。我将buildroot中相关的库替代板子上的库后系统无法启动了,说明板子上其他程序需要的版本还是2.27的,这样buildroot中编译的程序很多情况下是无法直接在ubuntu环境的板子上跑的。不知道rockchip为啥会将两个版本搞的不一致???
c)针对上面将PC上编译的Qt应用程序在板子上运行报错的问题,现在想到的一个办法是PC编译环境用编译出来的,而目标板子上的库不用编译出来的,直接用在网上安装的(安装方法 sudo apt-get install qt5-default),这样验证发现目前可以正常运行。因为暂时没有好的解决办法,所以暂时就这样处理了。但有一个潜在的问题是编译的库和运行的库版本不一致,有可能后续编译不报错,而程序在板子上运行会报错。
四、因为opencv是用cmake管理的,在编译过程中对cmake有一个初步认识了,记录一下
1)cmake管理的程序在编译之前需要执行cmake命令来生成Makefile,运行cmake的当前目录可以不是代码中CMakeLists.txt和代码所在的目录,一般会单独创建一个目录,比如build或在build_out等
比如是先在opencv目录下创建build_x86和build_rk3399,用于后续分别配置和编译pc和板子上用的目标文件。
2)进入build_x86,执行cmake .. ,两点表示CMakeList.txt所在的目录。
3)上面命令执行完成后Makefile会自动生成,直接make就ok了
4)这里有一个需要记录的是cmake会根据CMakeList.txt中的变量来生成Makefile中的相应变量,cmake中的变量大概有下面两种方式设在
a)在CMakeList.txt中通过set()函数来添加,比如:
set( CMAKE_CXX_FLAGS "-std=c++11" )
b)在执行cmake命令时作为参数输入,比如: cmake -D CMAKE_CXX_FLAGS="-std=c++11" ..
网上也有比较多cmake介绍的文章:
https://blog.csdn.net/qq_38109843/article/details/104746737
https://blog.csdn.net/weixin_36926794/article/details/80297929
五、在qt程序中如果要添加一些编译选项,可以在对应的pro文件中对QMAKE_CFLAGS和QMAKE_CXXFLAGS进行增加赋值就可以了,比如要增加OpenMP的支持的编译选项如下:
QMAKE_CFLAGS += -fopenmp
QMAKE_CXXFLAGS += -fopenmp