QT Cross Compile
Read time: 7 minute(s)
建立 git 仓库进行跟踪
因为在编译的时候会对 QT 进行部分的代码修改,建立仓库可以很好的跟踪修改记录
.gitignore
会把一些不需要的中间文件不进行跟踪
git init
git add *
vim .gitignore
git add .gitignore
git commit -m "init"
cat .gitignore
*.a
*.asn1.[ch]
*.bin
*.bz2
*.dwo
*.elf
*.gcno
*.gz
*.i
*.ko
*.lex.c
*.ll
*.lst
*.lz4
*.lzma
*.lzo
*.o
*.o.*
*.s
*.so
*.so.dbg
配置编译工具链
工具链的配置建议使用 qt 提供的 qmake 机制进行配置,配置文件在
mkspecs/qws目录下,通过两个文件完成配置
cd mkspecs/qws/
cp -r linux-arm-gnueabi-g++ linux-riscv-gnueabi-g++
cd linux-riscv-gnu-g++/
- qplatformdefs.h
- QT 代码本身兼容 32 位和 64 位,因此对于 64 位 CPU,不需要进行过多的设置
- qplatformdefs 进行一些基础的数据变量的定义,如 type,ipc 等,和 linux 平台的关联性更强,和 riscv
的关联性没有
cat qplatformdefs.h #include "../../linux-g++-64/qplatformdefs.h" cat ../../linux-g++-64/qplatformdefs.h #include "../linux-g++/qplatformdefs.h"
- qmake.conf
- qmake 配置了交叉编译的工具链信息,是交叉编译的主要
- qmake 并没有指定工具链的路径,因此需要编译前把路径手工加入到 PATH 环境变量
- export PATH=/xxx/d211/bin/:$PATH
- 包含工具参数的定义:QMAKE_COPY = cp -f
- qws.conf 中定义基础功能:QT += core gui network
# # qmake configuration for building with arm-none-linux-gnueabi-g++ # include(../../common/linux.conf) include(../../common/gcc-base-unix.conf) include(../../common/g++-unix.conf) include(../../common/qws.conf) # modifications to g++.conf QMAKE_CC = riscv64-unknown-linux-gnu-gcc QMAKE_CXX = riscv64-unknown-linux-gnu-g++ QMAKE_LINK = riscv64-unknown-linux-gnu-g++ QMAKE_LINK_SHLIB = riscv64-unknown-linux-gnu-g++ # modifications to linux.conf QMAKE_AR = riscv64-unknown-linux-gnu-ar cqs QMAKE_OBJCOPY = riscv64-unknown-linux-gnu-objcopy QMAKE_STRIP = riscv64-unknown-linux-gnu-strip load(qt_config)
- 环境变量
和传统的交叉编译不同,QT 采用的是 QMake 进行系统编译,编译方案是先进行一些 Host 的工具编译(采用 CC),再进行交叉编译(采用 CC),因此在设置环境变量时, 只可以添加交叉编译工具链到 PATH,设置 CC, 绝对不能设置 CC 的传统的交叉编译变量,否则出现莫名的问题。
如果需要 directfb 的支持,则需要明确指定一下 directfb 的路径,导如下两个环境变量export QT_CFLAGS_DIRECTFB="-I/xxx/install/include/directfb/" export QT_LIBS_DIRECTFB="-L/xxx/install/lib -ldirectfb -lfusion -ldirect -lpthread -lz"
编译
- configure
-
用最简单的编译方式编译,大部分功能先 disable,如果需要再打开
-
通过-xplatform qws/linux-arm-gnueabi-g++指定交叉编译工具链
-
configure 完成后会生成 Makefile
-
make distclean 命令无效,无法清除生成的 Makefile
./configure -opensource -confirm-license -xplatform qws/linux-riscv-gnueabi-g++ \ -prefix /xxx/install -plugin-gfx-directfb -no-qt3support \ -nomake demos -nomake examples -no-glib -depths 8,16,32 -qt-gfx-linuxfb -no-gfx-transformed \ -no-gfx-qvfb -no-gfx-vnc -no-gfx-multiscreen -no-mouse-pc -no-mouse-linuxtp -no-mouse-linuxinput \ -no-mouse-tslib -no-mouse-qvfb -no-kbd-tty -no-kbd-linuxinput -no-kbd-qvfb -release -shared \ -little-endian -embedded arm -no-gif -no-libmng -no-accessibility -no-libjpeg -no-libtiff -no-freetype \ -no-openssl -no-opengl -no-sql-sqlite -no-xmlpatterns -no-multimedia -no-audio-backend -no-phonon \ -no-phonon-backend -no-svg -no-webkit -script -no-scripttools -no-stl -no-declarative -no-pch \ -no-xinerama -no-cups -no-nis -no-separate-debug-info -fast -no-rpath
-
- swpb
汇编我们的工具链没有提供 swpb 汇编,需要直接使用 C 语言的交换方式完成
../../include/QtCore/../../src/corelib/arch/qatomic_armv5.h:128: Error: unrecognized opcode `swpb a3,a4,[s0]' diff --git a/src/corelib/arch/qatomic_armv5.h b/src/corelib/arch/qatomic_armv5.h index 27e23d9e..b265d149 100644 --- a/src/corelib/arch/qatomic_armv5.h +++ b/src/corelib/arch/qatomic_armv5.h @@ -125,10 +125,12 @@ Q_CORE_EXPORT __asm char q_atomic_swp(volatile char *ptr, char newval); inline char q_atomic_swp(volatile char *ptr, char newval) { register char ret; - asm volatile("swpb %0,%2,[%3]" - : "=&r"(ret), "=m" (*ptr) - : "r"(newval), "r"(ptr) - : "cc", "memory"); + //asm volatile("swpb %0,%2,[%3]" + // : "=&r"(ret), "=m" (*ptr) + // : "r"(newval), "r"(ptr) + // : "cc", "memory"); + ret = *ptr; + *ptr = newval; return ret; } @@ -227,10 +229,12 @@ inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) { int originalValue; #ifndef QT_NO_ARM_EABI - asm volatile("swp %0,%2,[%3]" - : "=&r"(originalValue), "=m" (_q_value) - : "r"(newValue), "r"(&_q_value) - : "cc", "memory"); + //asm volatile("swp %0,%2,[%3]" + // : "=&r"(originalValue), "=m" (_q_value) + // : "r"(newValue), "r"(&_q_value) + // : "cc", "memory"); + originalVlaue = _q_value; + _q_value = newValue;
- gnu 兼容工具链版本的不同,会使某些 C++ code 的兼容性会有差异,需要指定 gnu++98
error: 'std::tr1' has not been declared --- a/mkspecs/common/g++-base.conf +++ b/mkspecs/common/g++-base.conf @@ -15,7 +15,7 @@ QMAKE_LINK_C_SHLIB = $$QMAKE_CC QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += -O2 -g -QMAKE_CXX = g++ +QMAKE_CXX = g++ -std=gnu++98 QMAKE_LINK = $$QMAKE_CXX QMAKE_LINK_SHLIB = $$QMAKE_CXX --- a/mkspecs/common/gcc-base.conf +++ b/mkspecs/common/gcc-base.conf @@ -42,7 +42,7 @@ QMAKE_CFLAGS_STATIC_LIB += -fPIC QMAKE_CFLAGS_YACC += -Wno-unused -Wno-parentheses QMAKE_CFLAGS_HIDESYMS += -fvisibility=hidden -QMAKE_CXXFLAGS += $$QMAKE_CFLAGS +QMAKE_CXXFLAGS += $$QMAKE_CFLAGS -std=gnu++98 QMAKE_CXXFLAGS_DEPS += $$QMAKE_CFLAGS_DEPS
Directfb 集成
configure 会优先使用 pkg_config, directfb-config 两个工具进行 directfb 的路径获取,会很容易的受到系统 directfb 的影响,
因此此处最简单的办法的绕开系统的变量,直接设置 DIRECTFB
和 QT_LIBS_DIRECTFB 的变量值
The DirectFB screen driver functionality test failed!
--- a/configure
+++ b/configure
@@ -6641,13 +6641,13 @@ if [ "$PLATFORM_QWS" = "yes" ]; then
fi
if [ "${screen}" = "directfb" ] && [ "${CFG_CONFIGURE_EXIT_ON_ERROR}" = "yes" ]; then
- if test -n "$PKG_CONFIG" && "$PKG_CONFIG" --exists directfb 2>/dev/null; then
- QT_CFLAGS_DIRECTFB=`$PKG_CONFIG --cflags directfb 2>/dev/null`
- QT_LIBS_DIRECTFB=`$PKG_CONFIG --libs directfb 2>/dev/null`
- elif directfb-config --version >/dev/null 2>&1; then
- QT_CFLAGS_DIRECTFB=`directfb-config --cflags 2>/dev/null`
- QT_LIBS_DIRECTFB=`directfb-config --libs 2>/dev/null`
- fi
+ #if test -n "$PKG_CONFIG" && "$PKG_CONFIG" --exists directfb 2>/dev/null; then
+ # QT_CFLAGS_DIRECTFB=`$PKG_CONFIG --cflags directfb 2>/dev/null`
+ # QT_LIBS_DIRECTFB=`$PKG_CONFIG --libs directfb 2>/dev/null`
+ #elif directfb-config --version >/dev/null 2>&1; then
+ # QT_CFLAGS_DIRECTFB=`directfb-config --cflags 2>/dev/null`
+ # QT_LIBS_DIRECTFB=`directfb-config --libs 2>/dev/null`
+ #fi
config.test
config.tests
是 configure 的测试目录,其中有不少简单的 verify 示例,以 directfb 为例
config.tests/qws/directfb
directfb.cpp directfb.o directfb.pro Makefile
cat Makefile
CC = riscv64-unknown-linux-gnu-gcc
CXX = riscv64-unknown-linux-gnu-g++
DEFINES =
CFLAGS = -pipe -O2 -Wall -W $(DEFINES)
CXXFLAGS = -pipe -std=gnu++98 -D_REENTRANT -O2 -Wall -W $(DEFINES)
INCPATH = -I../../../mkspecs/qws/linux-riscv-gnueabi-g++ -I. -I/usr/include/directfb
LINK = riscv64-unknown-linux-gnu-g++
LFLAGS = -Wl,-O1
LIBS = $(SUBLIBS) -L/usr/lib/x86_64-linux-gnu -ldirectfb -lfusion -ldirect -lpthread
AR = riscv64-unknown-linux-gnu-ar cqs
- 如果某一 test 没有过,可以通过查看 Makefile 确认相关参数是否正确,如上的 include 参数不正确
- 如果参数正确,可以直接进入该目录执行 make 命令确认出错原因
- 最初编译 directfb 是动态 zlib,因此需要明确 zlib,第一次仿照上面的 LIBS 设置,则在编译的时候报告 zlib 的错误