树莓派学习::qt5.6.0交叉编译(armv8 64位).

Ubuntu16.04 x64环境下进行qt5交叉编译(armv8)


背景

交叉编译的作用

由于arm板子的性能有限,在性能强大的笔记本或者台式电脑上进行程序的调试和编译是很舒服的事情。当然,如果对速度没有追求,大可以在开发板上直接apt-get install qtcreator  , qt4等来配置环境,直接在开发板上进行编程。

 

测试环境

(1)硬件设备

  •  msi笔记本,I7-4710H,16G内存
  • 树莓派3b+,armv8(64位),16Gsd卡

(2)系统环境

  • 笔记本:ubuntu16.04 x64位
  • 树莓派3b+:debian9 x64位 
  • 建议 :如果要交叉编译 32位的程序,笔记本系统最好用32位,相反,如果要交叉编译出64位程序,笔记本系统 用64位,这样可以免去很多奇怪的报错

(3)你的疑惑:

问:树莓派官方并没有出64位的系统,为什么我的树莓派安装的是64位系统

答:个人需求,具体安装会在下文

 

环境配置 

一、树莓派环境安装

(1)64位系统映像下载:链接: https://pan.baidu.com/s/1T5kd8HHyuBYjRBJ-gKoiXQ 提取码: vkgr 

系统来源:OPENFANS开源社区-量子云&&树莓派爱好者基地。

(2) 系统烧写

  • 像官方系统一样烧写即可

(3)系统配置

1)创建文件sudo nano /etc/network/interfaces.d/wlan0

  • 由于给出的系统是纯净系统,没有ui界面,因此为了可以连上ssh,尽量在有网络的条件下进行
  • 开机即可使用ssh,关于有线网络IP请自行在路由器上检查。账户名:pi  密码:raspberry
  • 下面给出wifi设置教程,个人估计可以在sd卡上直接写入,那么就可以直接连wifi,当然也可以在ssh下设置

2)编辑文件,写入以下内容:

auto wlan0

allow-hotplug wlan0

iface wlan0 inet dhcp

wpa-ssid “你的无线SSID名称”

wpa-psk “你的无线SSID对应的密码”

3)保存退出

4)重启或输入sudo service networking restart即可正常使用

(4)安装桌面

#教程推荐使用mate桌面环境,个人也是用这个,希望有小伙伴尝试一下gnome,再来分享

sudo apt-get update

sudo apt-get install xserver-xorg -y 

sudo apt-get install mate-desktop-environment-core lightdm -y

重启之后即可看到久违的桌面 

 

二、笔记本ubuntu系统安装(不展开)

  • 请确保你的系统比较干净
  • 系统要进行update和upgrade

三 、 配置笔记本下的交叉编译环境

(1)问答:

问:什么交叉编译环境?

答:就是配置一个对应平台的g++编译器,比如说上面安装的树莓派3b+ 的64位系统,那么就要配置一个aarch64或arm64的g++编译器。

问:如何查看系统架构平台?

答:输入uname -a,如果有x86_64的就是64位,还可能出现arm64  aarch64等字样。其他自行查资料

问:如何配置这个g++编译器?

答:看下文

(2)对应平台的g++编译器配置,即配置交叉编译器

1)检查系统架构平台:uname -a

2)下载交叉编译器aarch64-linux-gnu-gcc

这里有旧版的和新版的可选,网上一片教程都用的旧版,个人用的是新版

旧版下载: 链接: https://pan.baidu.com/s/1tMFvsea1EFUxBx_K1u6BYg 提取码: xwpy 

新版下载:https://releases.linaro.org/components/toolchain/binaries/7.3-2018.05/aarch64-linux-gnu/

3) 配置这个交叉编译器

新建一个文件夹arm,解压:

 4)将路径写入PATH路径中,即打开文件:

sudo vim /etc/profile

5)在添加刚刚解压的文件夹的bin路径到PATH,即添加如下内容(具体路径自行根据环境修改):

export PATH=$PATH:/home/用户名/arm/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/

6)刷新:

source /etc/profile

7)检查配置是否完成(注意,两个都需要有正常输出,这一步才算完成):

aarch64-linux-gnu-g++ -v
sudo aarch64-linux-gnu-g++ -v

 正常来说应该有如下输出:

特殊情况有:

输入sudo aarch64-linux-gnu-g++ -v,提示没有找到命令,而直接输入aarch64-linux-gnu-g++ -v可正常显示

解决方案:在sudos配置文件下把交叉编译器的bin路径也加入

sudo vi /etc/sudoers

加入之后应该是这个样子:

这时再次输入sudo aarch64-linux-gnu-g++ -v,就应该可以正常输出版本信息了。

问:为什么一定要sudo aarch64-linux-gnu-g++ -v 也有正常输出?

答:因为在下面的编译过程中make中没有用到sudo,但是安装的时候要sudo make install,这一步的操作也需要交叉编译器,如果不正确配置,会出现make成功,而sudo make install失败的奇观。

(3)到这里,这个交叉编译环境就基本OK了

 

四、下载qt源码以及安装包

(1)问答:

问:为什么需要源码和安装包两个东西?

答:安装包是用来给本地装一个qt,源码是用来编译一个 对应平台的qt,即编译一个arm平台可用的qt

问:QT版本有要求吗?

答:这个qt版本的话就有点讲究了,个人在QT5.5的源码交叉编译中出现莫名其妙的错误,QT5.7的话版本有点新,没有尝试,最终利用QT5.6.0版本成功编译,所以推荐QT5.6.0

(2) 下载

安装包下载:http://download.qt.io/archive/qt/5.6/5.6.0/

源码下载:http://download.qt.io/archive/qt/5.6/5.6.0/single/

(3)利用安装包在本地安装

这个比较简单,一路next基本没问题

 

(4)依赖库安装:

sudo apt-get install qt5*-dev
sudo apt-get install qtbase5-dev
sudo apt-get install qtdeclarative5-dev qml-module-qtquick-controls

 

五、qt源码配置

(1)问答:

问:这个qt源码怎么用?

答:我们的目的是利用源码编译出一个arm平台的qt,所以需要先配置,然后编译

(2)编译平台信息配置

1)解压下载的源码包,路径没要求,一般在“/home/用户” 下就可以

2)进解压的文件夹浏览一番

3)找到qtbase,这个是编译出来的文件存放地方

cd qtbase

4)在qtbase中找到mkspecs文件夹 ,这个文件夹放置着各种平台下的编译配置信息,

cd mkspecs

5)在mkspecs文件夹中找到 linux-arm-gnueabi-g++文件夹,这个看起来就跟我们的平台很像,进入浏览

cd linux-arm-gnueabi-g++

 6)在 linux-arm-gnueabi-g++文件夹下,可以看到两个文件,其中qmake.conf是我们需要修改的文件

 7)qmake.conf原内容:

#
# qmake configuration for building with arm-linux-gnueabi-g++
#

MAKEFILE_GENERATOR      = UNIX
CONFIG                 += incremental
QMAKE_INCREMENTAL_STYLE = sublib

include(../common/linux.conf)
include(../common/gcc-base-unix.conf)
include(../common/g++-unix.conf)

# modifications to g++.conf
QMAKE_CC                = arm-linux-gnueabi-gcc
QMAKE_CXX               = arm-linux-gnueabi-g++
QMAKE_LINK              = arm-linux-gnueabi-g++
QMAKE_LINK_SHLIB        = arm-linux-gnueabi-g++

# modifications to linux.conf
QMAKE_AR                = arm-linux-gnueabi-ar cqs
QMAKE_OBJCOPY           = arm-linux-gnueabi-objcopy
QMAKE_NM                = arm-linux-gnueabi-nm -P
QMAKE_STRIP             = arm-linux-gnueabi-strip
load(qt_config)

8)修改:我们需要将原内容的arm-linux-gnueabi交叉编译器换成我们的,所以直接将上面的arm-linux-gnueabi换成aarch64-linux-gnu即可,当然,如果你下载的是其他交叉编译器,换成你对应的平台交叉编译器即可。如果不知道如何修改,可在终端上输入aarch64-linux-gnu-gcc -v,来看信息,然后用Target:后面的内容替换上面原内容中的arm-linux-gnueabi即可。

9)修改后的qmake.conf文件内容如下:

#
# qmake configuration for building with arm-linux-gnueabi-g++
#

MAKEFILE_GENERATOR      = UNIX
CONFIG                 += incremental
QMAKE_INCREMENTAL_STYLE = sublib

include(../common/linux.conf)
include(../common/gcc-base-unix.conf)
include(../common/g++-unix.conf)

# modifications to g++.conf
QMAKE_CC                = aarch64-linux-gnu-gcc
QMAKE_CXX               = aarch64-linux-gnu-g++
QMAKE_LINK              = aarch64-linux-gnu-g++
QMAKE_LINK_SHLIB        = aarch64-linux-gnu-g++

# modifications to linux.conf
QMAKE_AR                = aarch64-linux-gnu-ar cqs
QMAKE_OBJCOPY           = aarch64-linux-gnu-objcopy
QMAKE_NM                = aarch64-linux-gnu-nm -P
QMAKE_STRIP             = aarch64-linux-gnu-strip
load(qt_config)

10)到这里,配置的第一步完成了

(3)编译选项配置

1)这个就有点玄妙了 ,建议先阅读文章:[编译] QT编译./configure参数的详细解释[新手充电必读]

2)总的来说,就是通过./configure 后面加上我们的目标平台信息、要编译的库、不编译的库等一些列选项,来编译出一个我们需要的arm目标平台版本的qt

3)一些关键选项:

-prefix  后面填入编译安装后arm平台版本的qt路径(后面需要将这个qt复制到开发板)

-xplatform linux-arm-gnueabi-g++  这里就是选择我们刚刚修改完的目标平台信息,编译将会以这个目标平台为编译的目标

-no-pch、-no-iconv这几个no表示不编译这几个库,因为编译他们可能会导致奇怪的错误

-skip qtdeclarative 表示不编译qml、quick库,因为这两个库需要opengl库支持,这个问题的描述相关参考:

      1、https://blog.csdn.net/hhhlizhao/article/details/73604445

      2、http://www.qter.org/forum.php?mod=viewthread&tid=5563&extra=&ordertype=1

      3、https://www.qtcentre.org/threads/55438-Project-ERROR-Unknow-module(s)-in-QT-quick

      4、https://bugreports.qt.io/browse/QTBUG-32740

4)这里直接给出一个.sh文件,里面直接写好了一些选项,一般不建议新手进行修改

#!/bin/sh  
./configure -prefix /home/msi/arm/qt560_64/qt_sdk \
-opensource \
-release \
-no-pch \
-confirm-license \
-xplatform linux-arm-gnueabi-g++ \
-qt-zlib \
-no-iconv \
-no-gif \
-no-nis \
-qt-libjpeg \
-no-opengl \
-skip qtdeclarative \
-skip qtquickcontrols \
-skip qtquickcontrols2 \
-no-qml-debug \
-no-cups \
-no-glib \
-no-dbus \
-no-rpath \
-no-sse2 -no-sse3 -no-ssse3 -no-sse4.1 -no-sse4.2 \
-no-avx  \
-no-openssl \
-nomake tools \
-qreal float \
-qt-libpng \
-nomake examples

5)在qt源码根目录下,新建一个autoconfig.sh文件,将上面的内容复制到里面。

 (警告:上面内容每一行最后,即'\'的后面不能有空格,否则会运行报错)

gedit autoconfig.sh

6)赋权限

sudo chmod +x autoconfig.sh

7)运行,进行编译前的配置

./autoconfig

8)没有意外的话,输出如下:

Running configuration tests (phase 1)...
Done running configuration tests.
Creating qmake...
.........................................................................................Done.
Running configuration tests (phase 2)...
Warning: Disabling pkg-config since PKG_CONFIG_LIBDIR is not set and
the host's .pc files would be used (even if you set PKG_CONFIG_PATH).
Set this variable to the directory that contains target .pc files
for pkg-config to function correctly when cross-compiling or
use -pkg-config to override this test.
Warning: Disabling pkg-config since PKG_CONFIG_SYSROOT_DIR is not set.
Set this variable to your sysroot for pkg-config to function correctly when
cross-compiling or use -pkg-config to override this test.
Done running configuration tests.

   Configure summary

Building on:   linux-g++ (x86_64, CPU features: mmx sse sse2)
Building for:  linux-arm-gnueabi-g++ (arm64, CPU features: neon)
Platform notes:

            - Also available for Linux: linux-clang linux-kcc linux-icc linux-cxx
        
Build options:
  Configuration .......... accessibility audio-backend c++11 c++14 c++1z clock-gettime clock-monotonic compile_examples concurrent cross_compile enable_new_dtags evdev eventfd freetype full-config getaddrinfo getifaddrs harfbuzz inotify ipv6ifname large-config largefile linuxfb medium-config minimal-config mremap neon no-gif no-pkg-config pcre png posix_fallocate qpa qpa reduce_exports release shared small-config threadsafe-cloexec use_gold_linker zlib 
  Build parts ............  examples libs
  Mode ................... release
  Using sanitizer(s)...... none
  Using C++ standard ..... c++1z
  Using gold linker....... yes
  Using new DTAGS ........ yes
  Using PCH .............. no
  Using LTCG ............. no
  Target compiler supports:

Qt modules and options:
  Qt D-Bus ............... no
  Qt Concurrent .......... yes
  Qt GUI ................. yes
  Qt Widgets ............. yes
  Large File ............. yes
  QML debugging .......... yes
  Use system proxies ..... no

Support enabled for:
  Accessibility .......... yes
  ALSA ................... no
  CUPS ................... no
  Evdev .................. yes
  FontConfig ............. no
  FreeType ............... yes (bundled copy)
  Glib ................... no
  GStreamer .............. no
  GTK theme .............. no
  HarfBuzz ............... yes (bundled copy)
  Iconv .................. no
  ICU .................... no
  Image formats: 
    GIF .................. no
    JPEG ................. yes (plugin, using bundled copy)
    PNG .................. yes (in QtGui, using bundled copy)
  libinput................ no
  Logging backends: 
    journald ............... no
    syslog   ............... no
  mtdev .................. no
  Networking: 
    getaddrinfo .......... yes
    getifaddrs ........... yes
    IPv6 ifname .......... yes
    libproxy.............. no
    OpenSSL .............. no
  NIS .................... no
  OpenGL / OpenVG: 
    EGL .................. no
    OpenGL ............... no
    OpenVG ............... no
  PCRE ................... yes (bundled copy)
  pkg-config ............. no 
  PulseAudio ............. no
  QPA backends: 
    DirectFB ............. no
    EGLFS ................ no
      EGLFS i.MX6 ........ no
      EGLFS i.MX6 Wayland. no
      EGLFS EGLDevice .... no
      EGLFS GBM .......... no
      EGLFS Mali ......... no
      EGLFS Raspberry Pi . no
      EGLFS X11 .......... no
    LinuxFB .............. yes
    Mir client............ no
    XCB .................. no
  Session management ..... yes
  SQL drivers: 
    DB2 .................. no
    InterBase ............ no
    MySQL ................ no
    OCI .................. no
    ODBC ................. no
    PostgreSQL ........... no
    SQLite 2 ............. no
    SQLite ............... yes (plugin, using bundled copy)
    TDS .................. no
  tslib .................. no
  udev ................... no
  xkbcommon-x11........... no
  xkbcommon-evdev......... no
  zlib ................... yes (bundled copy)

Info: creating super cache file /home/msi/qt-everywhere-opensource-src-5.6.0/.qmake.super

Qt is now configured for building. Just run 'make'.
Once everything is built, you must run 'make install'.
Qt will be installed into /opt/arm/qt560_64/qt_sdk

Prior to reconfiguration, make sure you remove any leftovers from
the previous build.

9)头文件修改:

修改qtimageformats/src/3rdparty/libwebp/src/dsp/dsp.h文件: 

//#define WEBP_USE_NEON //注释第68行后就可以编译通过

否则,在接下来的make &&make install过程中会出现如下错误:

.obj/disk3/myown/qt-5.6/qtimageformats/src/3rdparty/libwebp/src/dsp/dec.o:dec.c:function VP8DspInit: error: undefined reference to ‘VP8DspInitNEON’ 
.obj/disk3/myown/qt-5.6/qtimageformats/src/3rdparty/libwebp/src/dsp/enc.o:enc.c:function VP8EncDspInit: error: undefined reference to ‘VP8EncDspInitNEON’ 
.obj/disk3/myown/qt-5.6/qtimageformats/src/3rdparty/libwebp/src/dsp/lossless.o:lossless.c:function VP8LDspInit: error: undefined reference to ‘VP8LDspInitNEON’ 
.obj/disk3/myown/qt-5.6/qtimageformats/src/3rdparty/libwebp/src/dsp/upsampling.o:upsampling.c:function WebPInitUpsamplers: error: undefined reference to ‘WebPInitUpsamplersNEON’ 
collect2: error: ld returned 1 exit status

10)编译文件修改:

修改/home/msi/qt-everywhere-opensource-src-5.6.0/qttools/src/src.pro

将SUBDIRS += linguist \  下面一行的qdoc删除,删除后的效果如下:

否则,在接下来的make &&make install过程中会出现(原因是qdoc这个包里面用到 qml,而我们在选项-skip qtdeclarative 设置了不编译qml,所以不删除这个qdoc会报错Project ERROR: Unknown module(s) in QT: qmldevtools-private):

cd qdoc/ && ( test -e Makefile || /home/msi/qt-everywhere-opensource-src-5.6.0/qtbase/bin/qmake /home/msi/qt-everywhere-opensource-src-5.6.0/qttools/src/qdoc/qdoc.pro -o Makefile ) && make -f Makefile install
Project ERROR: Unknown module(s) in QT: qmldevtools-private
Makefile:188: recipe for target 'sub-qdoc-install_subtargets' failed
make[2]: *** [sub-qdoc-install_subtargets] Error 3
make[2]: Leaving directory '/home/msi/qt-everywhere-opensource-src-5.6.0/qttools/src'
Makefile:56: recipe for target 'sub-src-install_subtargets' failed
make[1]: *** [sub-src-install_subtargets] Error 2
make[1]: Leaving directory '/home/msi/qt-everywhere-opensource-src-5.6.0/qttools'
Makefile:529: recipe for target 'module-qttools-install_subtargets' failed
make: *** [module-qttools-install_subtargets] Error 2


五、开始编译

(1)make

make -j4

经过相当长时间后,大概半小时,make完成,输出如下:

 (2)make  install

sudo make install

没报错的话,大概最后就这样,就算编译完成了

 

六、配置刚刚编译的对应平台qmake

(1)打开qtcreator

(2)点击选项,选择构建和运行

(3)选择编译器页面

1)点击右侧的添加:选择gcc

2)将路径设置为我们的交叉编译器aarch64-linux-gnu的路径 ,比如我的是:

3)添加完成,点应用

(4)选择Qt Versions页面

1)点击 右侧的添加

2)选择我们刚刚编译之前的配置选项--prefix路径的bin文件夹下的qmake,即armv8平台下的qmake

3)添加完成,点应用 

(5) 选择构建套件(kit)页面

1)点击 右侧添加

2)在编译器下拉列表框中选上我们刚刚添加的aarch64-linux-gnu-gcc/  g++ 编译器

3)在qt版本下拉列表框中选上我们刚刚添加的armv8的qt版本

4)kit配置完成如下

七、测试

(1)新建一个Qwidget项目

(2)在构建中选上刚刚添加的构建套件kit

(3)构建

(4)到构建的目录中查看文件类型

输入命令 

file 文件名

输出如下(表明是arm64平台的可执行文件 ):

 

八、开发板环境配置

(1)将上面ubuntu下编译qt是的编译选项--prefix 后的路径,这个文件夹复制到开发板上

我的路径如下:/home/msi/arm/qt560_64

复制到树莓派下:/home/pi/qt560_64

(2)开发板qt库路径配置

 配置Qt的运行时环境,打开/etc/profile,在最后一行输入一下内容:

export QTDIR=/home/pi/qt560_64/qt_sdk    #qtsdk在系统上的路径
export QT_QPA_FONTDIR=$QTDIR/lib/fonts 
export QT_QPA_PLATFORM_PLUGIN_PATH=$QTDIR/plugins/ 
export LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH 
export QT_QPA_PLATFORM=linuxfb:fb=/dev/fb0    #framebuffer驱动
export QWS_MOUSE_PROTO=/dev/input/event0

(3)刷新

source /etc/profile

 九、开发板测试

(1)将我们刚刚在笔记本ubuntu系统下新建的Qwidget工程编译出来的release文件夹复制到开发板上

(2)运行

(3)如果提示缺少类似libqtWidget.so.5.6等,在开发板上输入apt-get install qt5-default,将一些缺失的共享库补上就行

(4)运行效果 如下:


 十、总结

  • qt交叉编译是一个噩梦
  • 尽量使用高版本的qt,尽可能减少报错
  • 个人采用ubuntu16.04 X64+gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu + QT5.6.0 的交叉编译过程如上
  • 有网友采用ubuntu16.04 +gcc-linaro-aarch64-linux-gnu-4.9-2014.07_linux +QT5.6.0也编译成功 ,该文章如下:
  • https://blog.csdn.net/kaychangeek/article/details/80258464
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章