环境:
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 的宏定义。
在 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