参考文档

  1. Qt5.9.6源代码下载地址
  2. Qt5.9.6源代码百度云下载链接
  3. Qt官方编译指南
  4. Qt for Embedded Linux

开发环境介绍

  • 主机操作系统:Ubuntu16.04 64位
  • 目标平台:IMX.6
  • 交叉工具链:arm-poky-linux-gnueabi,gcc4.8.2
  • Qt版本:5.9.6
  • 编译时间:2018.7.7

提示:较新版本的Qt使用了C++11语法,所以必须使用gcc4.8.0及以上版本

配置交叉编译工具链

# 在/etc/bash.bashrc的最后增加如下指令

# Native Compiler
export AR_host="ar"
export CC_host="gcc"
export CXX_host="g++"
export LINK_host="g++"

# freescale imx.6 cross compiler, BoxV1
export ARCH=arm
export PATH=/opt/zhaozhongxiang/hwzt_yc_3.10.53/build-x11/tmp/sysroots/x86_64-linux/usr/bin/cortexa9hf-vfp-neon-poky-linux-gnueabi/:$PATH
# 修改完成之后需要重启命令行才能生效

配置编译环境

将sysroot拷贝到 /opt/zhaozhongxiang/hwzt_yc_3.10.53/build-x11/tmp/sysroots,因为Qt的依赖库比较多,所以建议针对目标器件建立sysroot目录,这里imx.6使用Ycoto生成的sysroot。如果sysroot过于精简,在执行配置脚本可能会出现依赖库缺失的情况,需要自己单独编译依赖库然后拷贝到sysroot目录,本文档将不单独介绍这部分内容。

另外需要着重注意sysroot对应的imx6qsabresd目录下存在之前编译的旧Qt版本的动态库,必须进行清除操作,否则将会影响新版本Qt的编译。

cd /opt/zhaozhongxiang/hwzt_yc_3.10.53/build-x11/tmp/sysroots/imx6qsabresd
sudo rm ./usr/lib/libQt* -rf
sudo rm ./usr/lib/qt5 -rf
安装系统依赖软件

因为编译环境涉及到使用64位Ubuntu操作系统交叉编译32位应用程序,所以需要另外安装一些依赖库。

sudo apt-get install gperf bison
sudo apt-get install ninja-build
sudo apt-get install libc6-dev-i386

针对Ubuntu16.04 64位操作系统:

sudo apt-get install gcc-multilib g++-multilib

针对Ubuntu14.04 64位操作系统:

sudo apt-get install gcc-4.8-multilib g++-4.8-multilib

创建配置脚本

在Qt源代码根目录创建build_configure.sh,内容如下:

#!/bin/bash

# configure bash for qt5.9.6
./configure -v \
    -opensource -confirm-license \
    -sysroot /opt/zhaozhongxiang/hwzt_yc_3.10.53/build-x11/tmp/sysroots/imx6qsabresd \
    -no-gcc-sysroot \
    -prefix /usr/local/Qt-5.9.6 \
    -device linux-imx6-g++ \
    -device-option CROSS_COMPILE=/opt/zhaozhongxiang/hwzt_yc_3.10.53/build-x11/tmp/sysroots/x86_64-linux/usr/bin/cortexa9hf-vfp-neon-poky-linux-gnueabi/arm-poky-linux-gnueabi- \
    -release -shared -make libs -verbose \
    -no-pch  \
    -no-rpath -pkg-config -accessibility -no-alsa -icu -dbus -no-glib \
    -no-directfb -eglfs -no-kms -linuxfb -xcb -xcb-xlib \
    -evdev -no-libinput -xinput2 -no-tslib -libudev -no-mtdev \
    -nomake examples -nomake tests \
    -fontconfig \
    -no-opengl -opengl es2 -egl -no-openvg \
    -system-zlib -system-libjpeg -system-libpng -system-xcb \
    -openssl-linked -qt-pcre -pulseaudio -no-sm \
    -no-sql-db2 -no-sql-ibase -no-sql-mysql -no-sql-oci -no-sql-odbc -no-sql-psql -no-sql-sqlite2 -no-sql-tds \
    -widgets -xkb

上述备注主要涉及到(按顺序):

  • -sysroot:目标文件系统,编译器会从这个目录寻找依赖库的头文件和库文件
  • -device:根据实际目标器件来填写,Qt支持的器件从qtbase/mkspecs/devices目录寻找
  • -device-option:配置编译器选项,这里配置了CROSS_COMPILE变量
  • -release:编译类型,支持-release、-debug,可以根据实际情况填写
  • -shared:库类型,将决定最终的Qt库的类型,支持-shared、-static
  • -verbose:显示编译时的打印信息
  • -eglfs:QPA平台编译开启,可以通过-no-eglfs关闭这个QPA,对于嵌入式设备的Qt webEngine必须使用eglfs平台渲染,否则会出现Web页面黑屏
  • -linuxfb:QPA平台编译开启,可以通过-no-linuxfb关闭这个QPA
  • -xcb:QPA平台编译开启,可以通过-no-xcb关闭这个QPA
  • -libudev:使用输入设备自动发现库
  • -nomake examples:建议关闭示例程序的编译
  • -nomake tests:建议关闭单元测试程序的编译
  • -opengl es2:开启opengl es2,对于嵌入式设备一定要开启这个设置
  • -egl:对于eglfs平台,一定要开启这个设置

提示:QPA:即QT平台抽象层,具体解释见参考文档4

通过configure脚本只是开启对各个QPA平台的校验,不意味成已经开启相应平台的支持,具体是否校验成功需要查看configure脚本最终打印的输出列表信息,如下图所示:

麒麟v10 arm nginx 麒麟v10 arm qtwebengine 离线安装包_imx6

从上图可以看到EGLFS i.Mx6的支持并没有开启,原因为sysroot中的EGL依赖库不是GPU版本,必须使用官方提供的GPU版本,将如下依赖库进行替换:

麒麟v10 arm nginx 麒麟v10 arm qtwebengine 离线安装包_imx6_02

另外在重新配置之前需要再替换一些动态库:

麒麟v10 arm nginx 麒麟v10 arm qtwebengine 离线安装包_qt_03

提示:上述动态库可以通过这里下载(下载地址)

重新执行build_configure.sh

rm config.cache
./build_configure.sh

提示:这里必须先清除config.cache才能重新进行一次配置检测,否则配置不会更新,更新之后的QPA信息如下图:

麒麟v10 arm nginx 麒麟v10 arm qtwebengine 离线安装包_imx6_04

修复Qt WebEngine Bug

在进行原始版本的Qt-5.9.6实际Webengine页面测试时发现html中的select元素(即下拉菜单)的位置会偏移到屏幕的左上角。如果应用程序需要使用Webengine模块建议按照下面的步骤修复这个Bug。

修改 qtbase/src/widgets/kernel/qwidgetbackingstore.cpp 文件中的 findTextureWidgetsRecursively 函数:

// 修改
    if (wd->renderToTexture) {
        QPlatformTextureList::Flags flags = 0;
        if (widget->testAttribute(Qt::WA_AlwaysStackOnTop))
            flags |= QPlatformTextureList::StacksOnTop;
        const QRect rect(widget->mapTo(tlw, QPoint()), widget->size());
        widgetTextures->appendTexture(widget, wd->textureId(), rect, wd->clipRect(), flags);
    }
// 为
    if (wd->renderToTexture) {
        QPlatformTextureList::Flags flags = 0;
        if (widget->testAttribute(Qt::WA_AlwaysStackOnTop))
            flags |= QPlatformTextureList::StacksOnTop;
        if ((widget->windowFlags() & Qt::WindowType_Mask) == Qt::ToolTip) {
            const QRect rect(widget->pos(), widget->size());
            widgetTextures->appendTexture(widget, wd->textureId(), rect, wd->clipRect(), flags); 
        } else {
            const QRect rect(widget->mapTo(tlw, QPoint()), widget->size());
            widgetTextures->appendTexture(widget, wd->textureId(), rect, wd->clipRect(), flags);
        }
    }

编译&安装

make -j8
make install

编译和安装正常完成之后会生成sysroot下的usr/local/Qt-5.9.6目录