环境:

ubuntu16.04(虚拟机)

QT版本:qt-everywhere-src-5.12.9

运行架构:ARMV7 / CSKY


        下文记录的交叉编译的目标运行架构为 ARMV7,同时也实验过 CSKY 架构,CSKY 架构的交叉编译过程大致一致,些许不同会在文中提出。

        对于 ubuntu 的环境差异,由于我使用时的 ubuntu 环境并不纯净,所以下文不涉及 ubuntu 环境方面的配置。

1:修改 qmake.conf 文件

        解压 QT 源码包后,其中会包含许多功能包,最基本也是最核心的 qtbase 包肯定是要交叉编译的。首先需要修改或新增 qmake.conf 文件。在 qtbase/mkspecs/ 目录下的各文件中都会存在 qmake.conf 文件。这个 qmake.conf 文件在随后配置 configure 时会用到。

        交叉编译 ARM 架构时,修改 qtbase/mkspecs/linux-arm-gnueabi-g++/qmake.conf 即可。

       交叉编译 CSKY 架构时,由于在 qtbase/mkspecs/ 下并没有合适的文件。所以参考 "linux-arm-gnueabi-g++" 文件新建了一个名为 "linux-csky-g++" 的文件。只需要修改 qmake.conf 文件。

        ARMV7 架构修改 qmake.conf 如下:

1 #
  2 # qmake configuration for building with arm-linux-gnueabi-g++
  3 #
  4 
  5 MAKEFILE_GENERATOR      = UNIX
  6 CONFIG                 += incremental
  7 QMAKE_INCREMENTAL_STYLE = sublib
  8 
  9 QT_QPA_DEFAULT_PLATFORM = linuxfb
 10 QMAKE_CFLAGS += -O2 -march=armv7-a -mtune=cortex-a7 -mfpu=neon -mfloat-abi=hard
 11 QMAKE_CXXFLAGS += -O2 -march=armv7-a -mtune=cortex-a7 -mfpu=neon -mfloat-abi=hard
 12 
 13 include(../common/linux.conf)
 14 include(../common/gcc-base-unix.conf)
 15 include(../common/g++-unix.conf)
 16 
 17 # modifications to g++.conf
 18 QMAKE_CC                = arm-linux-gnueabihf-gcc
 19 QMAKE_CXX               = arm-linux-gnueabihf-g++
 20 QMAKE_LINK              = arm-linux-gnueabihf-g++
 21 QMAKE_LINK_SHLIB        = arm-linux-gnueabihf-g++
 22 
 23 # modifications to linux.conf
 24 QMAKE_AR                = arm-linux-gnueabihf-ar cqs
 25 QMAKE_OBJCOPY           = arm-linux-gnueabihf-objcopy
 26 QMAKE_NM                = arm-linux-gnueabihf-nm -P
 27 QMAKE_STRIP             = arm-linux-gnueabihf-strip
 28 load(qt_config)
 29

        其中  "QMAKE_CFLAGS" 变量可以指定交叉编译时 C 编译器 flag 参数,"QMAKE_CXXFLAGS" 变量设置 C++ 编译器 flag 参数,这个具体的参数赋值和交叉工具链有关。在 CSKY 架构的 qmake.conf 中,也可以利用 "QMAKE_CFLAGS",和 "QMAKE_CXXFLAGS" 变量来指定目标 SOC 运行的 CPU 核心类型,当然,前提是你手中CSKY 架构的 SOC 存在多个核心。其余的修改参考上述代码修改即可。

        需要注意的是,工具链的路径已经加入到了环境变量之中,否则上述写法会找不到工具链。


2:利用 configure 脚本配置编译选项

        配置很长,可以总结配置项,写一个编译脚本。我写的编译脚本内容如下,仅供参考。

1 ./configure -prefix $(pwd)/arm-qt \
  2 -opensource \
  3 -confirm-license \
  4 -release \
  5 -strip \
  6 -shared \
  7 -xplatform linux-arm-gnueabi-g++ \
  8 -optimized-qmake \
  9 -c++std c++11 \
 10 --rpath=no \
 11 -pch \
 12 -skip qt3d \
 13 -skip qtactiveqt \
 14 -skip qtandroidextras \
 15 -skip qtcanvas3d \
 16 -skip qtconnectivity \
 17 -skip qtdatavis3d \
 18 -skip qtdoc \
 19 -skip qtgamepad \
 20 -skip qtlocation \
 21 -skip qtmacextras \
 22 -skip qtnetworkauth \
 23 -skip qtpurchasing \
 24 -skip qtremoteobjects \
 25 -skip qtscript \
 26 -skip qtscxml \
 27 -skip qtsensors \
 28 -skip qtspeech \
 29 -skip qtsvg \
 30 -skip qttools \
 31 -skip qttranslations \
 32 -skip qtwayland \
 33 -skip qtwebengine \
 34 -skip qtwebview \
 35 -skip qtwinextras \
 36 -skip qtx11extras \
 37 -skip qtxmlpatterns \
 38 -make libs \
 39 -make examples \
 40 -nomake tools -nomake tests \
 41 -gui \
 42 -widgets \
 43 -dbus-runtime \
 44 --glib=no \
 45 --iconv=no \
 46 --pcre=qt \
 47 --zlib=qt \
 48 -no-openssl \
 49 --freetype=qt \
 50 --harfbuzz=qt \
 51 -no-opengl \
 52 -linuxfb \
 53 --xcb=no \
 54 -tslib \
 55 --libpng=qt \
 56 --libjpeg=qt \
 57 --sqlite=qt \
 58 -plugin-sql-sqlite \
 59 -no-tslib \
 60 -recheck-all

        其中 -xplatform 参数指定上述修改 qmake.conf 所在的文件夹。 -skip 参数可以跳过不编译相应的功能包,否则编译时间会很长。第 59 行的 -no-tslib 表示不支持 tslib 控件。若需要搭配 tslib 实现触摸功能,需要先交叉编译 tslib。然后使用 "-I" 参数指定交叉编译的 tslib 安装目录的 include 文件。使用 "-L" 参数指定交叉编译的 tslib 安装目录的 lib 文件。

        然后执行编译脚本编译,注意 PC linux 中需要安装 g++ 。执行 sudo apt-get install g++ 即可。当出现 “Qt is now configure for building just run make” 提示后。就可以开始 make 编译源码了。


3:执行 make 开始编译

        在执行 make 编译时,ARM 架构并未遇到什么问题,CSKY 架构有个地方会报错,报错信息如下:

error Target architecture was not detected as supported by Double-Conversion.

        看提示信息是在 QT 源码中检测不到 CSKY 架构支持 Double-Conversion。这个问题可通过修改 QT 源码解决,在 qtbase/src/3rdparty/double-conversion/include/double-conversion/utils.h 文件中,在如下图所示位置增加 CSKY 的宏定义。

docker qt 交叉编译_docker qt 交叉编译

         在 make 结束后,执行 make install 就会在 configure 配置时的 --prefix 参数指定的目录中安装交叉编译后的文件。


4:移植到根文件系统测试

        我的根文件系统使用 buildroot 生成,当然,buildroot 也可以生成 QT。将上述交叉编译得到的 arm-qt 文件复制到 rootfs 的 /usr/lib/ 目录下,然后编辑 /etc/profile,加入如下内容,仅供参考。

11 export QT_ROOT=/usr/lib/arm-qt
 12 export QT_QPA_GENERIC_PLUGINS=tslib:/dev/input/event1
 13 export QT_QPA_FONTDIR=/usr/share/fonts/liberation/
 14 export QT_QPA_PLATFORM=linuxfb:tty=/dev/fb0
 15 export QT_PLUGIN_PATH=$QT_ROOT/plugins
 16 export QT_LIBRARY_PATH=$QT_ROOT/lib:$QT_ROOT/plugins/platforms
 17 export QML2_IMPORT_PATH=$QT_ROOT/qml
 18 export QT_QPA_FB_TSLIB=1
 19 
 20 export LD_LIBRARY_PATH=$PKG_CONFIG_PATH:\
 21 /usr/lib/arm-qt/lib

        当在 rootfs 中指定完 QT 的环境变量后,需要刷新 /etc/profile 文件,使用 source /etc/profile 命令即可刷新。然后便可以执行 QT 自带的演示程序来判断是否正确移植。路径如下

/usr/lib/arm-qt/examples/widgets/animation/animatedtiles/animatedtiles