一、编译主机环境搭建
ubuntu20.04主机系统下载:https://releases.ubuntu.com/
编译主机依赖安装:
sudo apt-get update
sudo apt-get install -y cmake gcc g++ vim iputils-ping net-tools \
openssh-server openssh-client gcc-aarch64-linux-gnu \
g++-aarch64-linux-gnu binutils-aarch64-linux-gnu qemu-user-static \
二、QT编译
1).QT下载:https://download.qt.io/archive/qt/
国内地址:https://mirrors.tuna.tsinghua.edu.cn/qt/archive/qt/
2).解压QT源码:
mkdir -p ~/project
tar -xvf qt-everywhere-opensource-src-5.15.12.tar.xz -C ~/project
cd ~/project/qt-everywhere-src-5.15.12/ #进入源码目录
3).创建QT配置脚本autoconfig.sh,内容如下:
#!/bin/sh
./configure \
-sysroot /opt/sysroot/host \
-extprefix /opt/qt5.15.12-aarch64 \
-confirm-license \
-opensource \
-release \
-make libs \
-xplatform linux-aarch64-gnu-g++ \
-pch \
-qt-libjpeg \
-qt-libpng \
-qt-zlib \
-no-sse2 \
-no-openssl \
-no-cups \
-no-separate-debug-info \
-gui \
-widgets \
-glib \
-opengl es2 \
-egl \
-eglfs \
-qpa eglfs \
-xcb \
-dbus \
-syslog \
-sqlite \
-tslib \
-fontconfig \
-no-harfbuzz \
-no-linuxfb \
-no-directfb \
-recheck-all
注:配置有变动修改这个文件即可,修改完成后运行"./autoconfig.sh"生效配置。另外不同版本这部分会有差异需根据实际情况修改。
4).修改qmake配置。
qtbase/mkspecs/linux-aarch64-gnu-g++/qmake.conf
#
# qmake configuration for building with aarch64-linux-gnu-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
QMAKE_INCDIR_OPENGL_ES2 = $$[QT_SYSROOT]/usr/include
QMAKE_LIBDIR_OPENGL_ES2 = /usr/lib/aarch64-linux-gnu
QMAKE_INCDIR_EGL = $$[QT_SYSROOT]/usr/include
QMAKE_LIBDIR_EGL = /usr/lib/aarch64-linux-gnu
QMAKE_LIBS_EGL += -lEGL -lGLESv2
QMAKE_LIBS_OPENGL_ES2 += -lGLESv2 -lEGL
load(qt_config)
5).QT编译依赖
autoconfig.sh中的"-sysroot"指定了目标文件系统的位置, QT编译过程会从这个位置获取需要的依赖库。这里将目标文件系统复制到"-sysroot"指定的目录中。
sudo chmod 777 /opt/
mkdir -p /opt/sysroot/host
rsync -avx 目标文件系统根目录 /opt/sysroot/host
目标文件系统可能因缺少某些库,导致配置阶段报错,如后面"编译过程遇到的问题章节"介绍。可以参考下面方法解决。
创建"/opt/sysroot/host/ch-mount.sh "内容如下:
#!/bin/bash
#
function mnt() {
echo "MOUNTING..."
sudo mount -t proc /proc ${2}proc
sudo mount -t sysfs /sys ${2}sys
sudo mount -o bind /dev ${2}dev
sudo mount -o bind /dev/pts ${2}dev/pts
echo "CHROOT..."
sudo chroot ${2}
echo "Success!"
}
function umnt() {
echo "UNMOUNTING"
sudo umount ${2}proc
sudo umount ${2}sys
sudo umount ${2}dev/pts
sudo umount ${2}dev
}
if [ "$1" == "-m" ] && [ -n "$2" ] ;
then
mnt $1 $2
elif [ "$1" == "-u" ] && [ -n "$2" ];
then
umnt $1 $2
else
echo ""
echo "Either 1'st, 2'nd or both parameters were missing"
echo ""
echo "1'st parameter can be one of these: -m(mount) OR -u(umount)"
echo "2'nd parameter is the full path of rootfs directory(with trailing '/')"
echo ""
echo "For example: ch-mount -m /media/sdcard/"
echo ""
echo 1st parameter : ${1}
echo 2nd parameter : ${2}
fi
cd /opt/sysroot/
chmod +x ch-mount.sh
./ch-mount.sh -m host #进入文件系统,
./ch-mount.sh -u host #exit退出后需要执行下面命令
通过"./ch-mount.sh -m host"进入后就可以通过apt-get下载软件包了。
6).openGL
前面我们在qmake.config中指定了openGL的依赖,但是这里的默认依赖关联的是mesa库,
root@ubuntu:/usr/lib/aarch64-linux-gnu# ls -la | grep "EGL"
lrwxrwxrwx 1 linaro linaro 20 Mar 9 2022 libEGL_mesa.so.0 -> libEGL_mesa.so.0.0.0
-rw-r--r-- 1 linaro linaro 259072 Mar 9 2022 libEGL_mesa.so.0.0.0
lrwxrwxrwx 1 linaro linaro 11 Mar 8 2022 libEGL.so -> libEGL.so.1
lrwxrwxrwx 1 linaro linaro 15 Mar 8 2022 libEGL.so.1 -> libEGL.so.1.1.0
-rw-r--r-- 1 linaro linaro 80312 Mar 8 2022 libEGL.so.1.1.0
root@ubuntu:/usr/lib/aarch64-linux-gnu# ls -la | grep "GLES"
lrwxrwxrwx 1 linaro linaro 17 Mar 8 2022 libGLESv1_CM.so -> libGLESv1_CM.so.1
lrwxrwxrwx 1 linaro linaro 21 Mar 8 2022 libGLESv1_CM.so.1 -> libGLESv1_CM.so.1.2.0
-rw-r--r-- 1 linaro linaro 141408 Mar 8 2022 libGLESv1_CM.so.1.2.0
lrwxrwxrwx 1 linaro linaro 14 Mar 8 2022 libGLESv2.so -> libGLESv2.so.2
lrwxrwxrwx 1 linaro linaro 18 Mar 8 2022 libGLESv2.so.2 -> libGLESv2.so.2.1.0
-rw-r--r-- 1 linaro linaro 149600 Mar 8 2022 libGLESv2.so.2.1.0
为了能正常使用mali库进行GPU加速,需要创建下面符号链接,让openGL关联的依赖变成mali库。
ln -sf mali/libEGL.so libEGL.so.1
ln -sf mali/libGLESv2.so libGLESv2.so.2
root@ubuntu:/usr/lib/aarch64-linux-gnu# ls -la | grep "GLES"
lrwxrwxrwx 1 linaro linaro 17 Mar 8 2022 libGLESv1_CM.so -> libGLESv1_CM.so.1
lrwxrwxrwx 1 linaro linaro 21 Mar 8 2022 libGLESv1_CM.so.1 -> libGLESv1_CM.so.1.2.0
-rw-r--r-- 1 linaro linaro 141408 Mar 8 2022 libGLESv1_CM.so.1.2.0
lrwxrwxrwx 1 linaro linaro 14 Mar 8 2022 libGLESv2.so -> libGLESv2.so.2
lrwxrwxrwx 1 root root 17 Jun 3 08:41 libGLESv2.so.2 -> mali/libGLESv2.so
-rw-r--r-- 1 linaro linaro 149600 Mar 8 2022 libGLESv2.so.2.1.0
root@ubuntu:/usr/lib/aarch64-linux-gnu# ls -la | grep "EGL"
lrwxrwxrwx 1 linaro linaro 20 Mar 9 2022 libEGL_mesa.so.0 -> libEGL_mesa.so.0.0.0
-rw-r--r-- 1 linaro linaro 259072 Mar 9 2022 libEGL_mesa.so.0.0.0
lrwxrwxrwx 1 linaro linaro 11 Mar 8 2022 libEGL.so -> libEGL.so.1
lrwxrwxrwx 1 root root 14 Jun 3 08:41 libEGL.so.1 -> mali/libEGL.so
-rw-r--r-- 1 linaro linaro 80312 Mar 8 2022 libEGL.so.1.1.0
7).编译安装
make
make install #安装位置为配置中"-extprefix"指定的位置。
三、部署
将上面"-extprefix"指定目录下的文件进行压缩,然后复制到开发板上相同的目录下。
#编译主机
cd /opt
tar -cvf qt5.15.12-aarch64.tar qt5.15.12-aarch64
#开发板
tar -xvf qt5.15.12-aarch64.tar -C /opt/
配置环境变量:
export QT_QPA_PLATFORM=XCB
export QT_QPA_EGLFS_INTEGRATION=XCB_EGL #没有这个有些应用会报0x03001错误。
export QTDIR=/opt/qt5.15.12-aarch64
export LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH
export QT_QPA_PLATFORM_PLUGIN_PATH=$QTDIR/plugins
export QML2_IMPORT_PATH=$QTDIR/qml
#export QT_QPA_PLATFORM=eglfs #直接配置它启动桌面可能有问题,要用到eglfs可以指定-platform参数
四、编译过程遇到的问题
注意下面需要安装的软件包都是安装在目标文件系统中。
-
xcb报错
ERROR: Feature 'xcb' was enabled, but the pre-condition 'features.thread && libs.xcb && tests.xcb_syslibs && features.xkbcommon-x11' failed.
解决方法:apt-get install libxcb1-dev libx11-xcb-dev libxcb-xkb-dev libxkbcommon-dev libxkbcommon-x11-dev libxcb-icccm4-dev
libxcb-image0-dev libxcb-keysyms1-dev libxcb-util-dev libxcb-randr0-dev libxcb-render-util0-dev libxcb-shape0-dev
libxcb-sync-dev libxcb-xfixes0-dev libxcb-xinerama0-dev -
sqlite3报错
ERROR: Feature 'system-sqlite' was enabled, but the pre-condition 'features.sql-sqlite && libs.sqlite3' failed.
解决方法:apt-get install -y libsqlite3-dev
-
tslib报错:
ERROR: Feature 'tslib' was enabled, but the pre-condition 'libs.tslib' failed.
解决方法:apt-get install libts-dev
-
缺少fbdev_window.h
main.cpp:2:10: fatal error: EGL/fbdev_window.h: No such file or directory
2 | #include <EGL/fbdev_window.h>
| ^~~~~~~~~~~~~~~~~~~~
compilation terminated.
make: *** [Makefile:169: main.o] Error 1
test config.qtbase_gui.tests.egl-mali FAILED
executing config test egl-mali-2
解决方法:
创建文件/usr/include/EGL/fbdev_window.h写入下面内容:
/*
1. This confidential and proprietary software may be used only as
2. authorised by a licensing agreement from ARM Limited
3. (C) COPYRIGHT 2008-2011 ARM Limited
4. ALL RIGHTS RESERVED
5. The entire notice above must be reproduced on all authorised
6. copies and copies may only be made to the extent permitted
7. by a licensing agreement from ARM Limited.
*/
/**
8. @file fbdev_window.h
9. @brief A window type for the framebuffer device (used by egl and tests)
*/
#ifndef _FBDEV_WINDOW_H_
#define _FBDEV_WINDOW_H_
#ifdef __cplusplus
extern "C" {
#endif
typedef enum
{
FBDEV_PIXMAP_DEFAULT = 0,
FBDEV_PIXMAP_SUPPORTS_UMP = (1<<0),
FBDEV_PIXMAP_ALPHA_FORMAT_PRE = (1<<1),
FBDEV_PIXMAP_COLORSPACE_sRGB = (1<<2),
FBDEV_PIXMAP_EGL_MEMORY = (1<<3) /* EGL allocates/frees this memory */
} fbdev_pixmap_flags;
typedef struct fbdev_window
{
unsigned short width;
unsigned short height;
} fbdev_window;
typedef struct fbdev_pixmap
{
unsigned int height;
unsigned int width;
unsigned int bytes_per_pixel;
unsigned char buffer_size;
unsigned char red_size;
unsigned char green_size;
unsigned char blue_size;
unsigned char alpha_size;
unsigned char luminance_size;
fbdev_pixmap_flags flags;
unsigned short *data;
unsigned int format; /* extra format information in case rgbal is not enough, especially for YUV formats */
} fbdev_pixmap;
#ifdef __cplusplus
}
#endif
#endif
-
openGL报错
ERROR: Feature 'opengles2' was enabled, but the pre-condition '(config.win32 && !features.opengl-dynamic) || (!config.watchos && !features.opengl-desktop && libs.opengl_es2)' failed.
ERROR: Feature 'egl' was enabled, but the pre-condition '(features.opengl || features.openvg) && (features.angle || libs.egl) && (features.dlopen || !config.unix || config.integrity)' failed.
ERROR: Feature 'eglfs' was enabled, but the pre-condition '!config.android && !config.darwin && !config.win32 && !config.wasm && features.egl' failed.
ERROR: The OpenGL functionality tests failed!
/usr/lib/gcc-cross/aarch64-linux-gnu/9/../../../../aarch64-linux-gnu/bin/ld: main.o: in function
main': main.cpp:(.text.startup+0x10): undefined reference toglUniform1f'
/usr/lib/gcc-cross/aarch64-linux-gnu/9/../../../../aarch64-linux-gnu/bin/ld: main.cpp:(.text.startup+0x18): undefined reference to `glClear'
collect2: error: ld returned 1 exit status
make: *** [Makefile:67: opengl_es2] Error 1
解决办法:
通过下面命令可以查到,这两个函数位于libmali.so中,所以我们需要在qmake.conf给openGL把这个依赖也要加上。
QMAKE_LIBS_EGL += -lEGL -lGLESv2 -lmali
QMAKE_LIBS_OPENGL_ES2 += -lGLESv2 -lEGL -lmali
-
配置正常,执行QT编译过程报函数未定义错误。
/usr/lib/gcc-cross/aarch64-linux-gnu/9/../../../../aarch64-linux-gnu/bin/ld: .obj/qlibrary_unix.o: in function
QLibraryPrivate::load_sys()': qlibrary_unix.cpp:(.text+0xbb0): warning: Using 'dlopen' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking /usr/lib/gcc-cross/aarch64-linux-gnu/9/../../../../aarch64-linux-gnu/bin/ld: /opt/sysroot/host/usr/lib/aarch64-linux-gnu/libpthread.a(pthread_create.o): in functionallocate_stack':
/build/glibc-fci4Zo/glibc-2.31/nptl/allocatestack.c:525: undefined reference to_dl_stack_flags' /usr/lib/gcc-cross/aarch64-linux-gnu/9/../../../../aarch64-linux-gnu/bin/ld: /build/glibc-fci4Zo/glibc-2.31/nptl/allocatestack.c:525: undefined reference to_dl_stack_flags'
/usr/lib/gcc-cross/aarch64-linux-gnu/9/../../../../aarch64-linux-gnu/bin/ld: /build/glibc-fci4Zo/glibc-2.31/nptl/allocatestack.c:647: undefined reference to_dl_stack_flags' /usr/lib/gcc-cross/aarch64-linux-gnu/9/../../../../aarch64-linux-gnu/bin/ld: /build/glibc-fci4Zo/glibc-2.31/nptl/allocatestack.c:647: undefined reference to_dl_stack_flags'
/usr/lib/gcc-cross/aarch64-linux-gnu/9/../../../../aarch64-linux-gnu/bin/ld: /opt/sysroot/host/usr/lib/aarch64-linux-gnu/libpthread.a(unwind.o): in function_jmpbuf_sp': /build/glibc-fci4Zo/glibc-2.31/nptl/../sysdeps/aarch64/jmpbuf-offsets.h:52: undefined reference to__pointer_chk_guard_local'
解决办法:
这个是因为目标系统的"/usr/lib/aarch64-linux-gnu"下有部分库的符号链接连接的是绝对路径。当被复制到编译主机上时这个绝对路径就指向了编译主机lib库。这里只需要将绝对路径全部替换成相对路径即可。
目标文件系统执行下面命令修改:
cd /usr/lib/aarch64-linux-gnu
ls -la | grep "lib/" #会查到下面内容
lrwxrwxrwx 1 root root 39 Jun 2 16:36 libanl.so -> /lib/aarch64-linux-gnu/libanl.so.1
lrwxrwxrwx 1 root root 45 Jun 2 16:36 libblkid.so -> /lib/aarch64-linux-gnu/libblkid.so.1.1.0
lrwxrwxrwx 1 root root 48 Jun 2 16:36 libBrokenLocale.so -> /lib/aarch64-linux-gnu/libBrokenLocale.so.1
lrwxrwxrwx 1 root root 45 Jun 2 16:36 libcrypt.so -> /lib/aarch64-linux-gnu/libcrypt.so.1.1.0
lrwxrwxrwx 1 root root 48 Jun 2 16:36 libdbus-1.so -> /lib/aarch64-linux-gnu/libdbus-1.so.3.19.11
lrwxrwxrwx 1 root root 38 Jun 2 16:36 libdl.so -> /lib/aarch64-linux-gnu/libdl.so.2
#......部分内容省略......
#以第一个为例,执行下面命令,修改成相对路径。
ln -sf ../../lib/aarch64-linux-gnu/libanl.so.1 libanl.so
ls -la | grep "lib/" #再次查到下面内容
lrwxrwxrwx 1 root root 39 Jun 2 16:36 libanl.so -> ../../lib/aarch64-linux-gnu/libanl.so.1
lrwxrwxrwx 1 root root 45 Jun 2 16:36 libblkid.so -> ../../lib/aarch64-linux-gnu/libblkid.so.1.1.0
lrwxrwxrwx 1 root root 48 Jun 2 16:36 libBrokenLocale.so -> ../../lib/aarch64-linux-gnu/libBrokenLocale.so.1
lrwxrwxrwx 1 root root 45 Jun 2 16:36 libcrypt.so -> ../../lib/aarch64-linux-gnu/libcrypt.so.1.1.0
lrwxrwxrwx 1 root root 48 Jun 2 16:36 libdbus-1.so -> ../../lib/aarch64-linux-gnu/libdbus-1.so.3.19.11
lrwxrwxrwx 1 root root 38 Jun 2 16:36 libdl.so -> ../../lib/aarch64-linux-gnu/libdl.so.2
#......部分内容省略......