Ubuntu下安装ARM交叉编译器

1.安装编译器与工具
sudo apt-get install g++-4.8-multilib-arm-linux-gnueabihf binutils-arm-linux-gnueabihf

2.查看是否安装完成
root@vm-zinc:/home/zeno# arm-linux-gnueabihf-g++-4.8 -v
Using built-in specs.
COLLECT_GCC=arm-linux-gnueabihf-g++-4.8
COLLECT_LTO_WRAPPER=/usr/lib/gcc-cross/arm-linux-gnueabihf/4.8/lto-wrapper
Target: arm-linux-gnueabihf
Configured with: ../src/configure -v –with-pkgversion=’Ubuntu/Linaro 4.8.2-16ubuntu4′ –with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs –enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ –prefix=/usr –program-suffix=-4.8 –enable-shared –enable-linker-build-id –libexecdir=/usr/lib –without-included-gettext –enable-threads=posix –with-gxx-include-dir=/usr/arm-linux-gnueabihf/include/c++/4.8.2 –libdir=/usr/lib –enable-nls –with-sysroot=/ –enable-clocale=gnu –enable-libstdcxx-debug –enable-libstdcxx-time=yes –enable-gnu-unique-object –disable-libmudflap –disable-libitm –disable-libquadmath –enable-plugin –with-system-zlib –disable-browser-plugin –enable-java-awt=gtk –enable-gtk-cairo –with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-armhf-cross/jre –enable-java-home –with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-armhf-cross –with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-armhf-cross –with-arch-directory=arm –with-ecj-jar=/usr/share/java/eclipse-ecj.jar –disable-libgcj –enable-objc-gc –enable-multiarch –enable-multilib –disable-sjlj-exceptions –with-arch=armv7-a –with-fpu=vfpv3-d16 –with-float=hard –with-mode=thumb –disable-werror –enable-checking=release –build=x86_64-linux-gnu –host=x86_64-linux-gnu –target=arm-linux-gnueabihf –program-prefix=arm-linux-gnueabihf- –includedir=/usr/arm-linux-gnueabihf/include
Thread model: posix
gcc version 4.8.2 (Ubuntu/Linaro 4.8.2-16ubuntu4)

3.利用交叉编译器编译QT
如果是交叉编译,需要配置 xplatform选项,比如要在arm-linux平台上移植Qt的话,就在配置项中加上 -xplatform linux-arm-gnueabi-g++ ,Qt5支持的交叉平台都可在源码顶层目录中的 /qtbase/mkspecs/ 下找到,每个子目录名代表一个交叉平台的名字,移植Qt时应根据自己的实际情况修改平台对应的子目录下的qmake.conf文件,它定义了一些与平台相关的环境变量,如交叉编译器等;

最好不要在编译Qt时使能 c++11,一方面你的编译器可能不支持,另一方面使能这一项后可能出现一部分编译错误;

如果需要openGL,就需要用 -opengl选项指定opengl的api,对于嵌入式平台,一般使用 opengl ES2,配置选项中加入” -opengl es2 ” 。不过想使用openGL可能会比较麻烦,因为openGL一般在有硬件图形加速的条件下才能高效运行,而这需要显卡或Soc厂家提供openGL的支持库,但并不是所有Soc都能找到对应的支持库,比如三星就没有提供S5PV210的openGL库,所以我这里编译的Qt也是没有opengl的。(openGL的替代方案:如果没有厂家提供的硬件图形库,可以考虑使用纯软件实现的opengl,这样的软件库有很多是开源的,如mesa3D库等,不过纯软件实现的opengl在效率方面肯定要比带硬件加速的低很多,而且要想在嵌入式平台上使用,必须将opengl的软件库也交叉编译出来,我在交叉编译mesa3D时遇到了些问题,所以目前还没能在开发板上用上openGL);

如果想让Qt程序支持多点触摸,在配置时可能需要加上 -mtdev 和 -xinput2 选项,在help中可以找到这两个选项。mtdev包含了应用程序对多点触摸协议的支持,xinput2实现了Linux的输入子系统对多点触摸的支持。在我这里加上这两个选项的话配置会出错,可能还缺乏一些库,所以最后我没有使用这两个选项;

另外,Qt5默认的qreal类型是64bit的double,如果希望用float类型定义qreal,则在配置选项中加入”-qreal float”。

我们是在arm板上移植,需要知道芯片的架构。我的是Cortex-A7,其架构是armv7-a。安装Host上的QT的时候选择安装源代码,然后进入到源码目录,进入~/Qt5.4.1/5.4/qtbase/Src/qtbase/mkspecs/linux-arm-gnueabi-g++目录下,需要修改qmake.conf文件。如下

 
#
# qmake configuration for building with arm-linux-gnueabi-g++
#

MAKEFILE_GENERATOR      = UNIX
CONFIG                 += incremental
QMAKE_INCREMENTAL_STYLE = sublib

//添加的内容
QT_QPA_DEFAULT_PLATFORM = linux #eglfs  
QMAKE_CFLAGS_RELEASE   += -O2 -march=armv7-a    
QMAKE_CXXFLAGS_RELEASE += -O2 -march=armv7-a

include(../common/linux.conf)
include(../common/gcc-base-unix.conf)
include(../common/g++-unix.conf)

# modifications to g++.conf
QMAKE_CC                = arm-linux-gnueabihf-g++-4.8
QMAKE_CXX               = arm-linux-gnueabihf-g++-4.8
QMAKE_LINK              = arm-linux-gnueabihf-g++-4.8
QMAKE_LINK_SHLIB        = arm-linux-gnueabihf-g++-4.8

# modifications to linux.conf
QMAKE_AR                = arm-linux-gnueabihf-ar cqs
QMAKE_OBJCOPY           = arm-linux-gnueabihf-objcopy
QMAKE_NM                = arm-linux-gnueabihf-nm -P
QMAKE_STRIP             = arm-linux-gnueabihf-strip
load(qt_config)

仅使用framebuffer,如果支持opengl es,可以使用eglfs。qt5将显示都做成了插件形式,这提供了更多的灵活性,详细的内容可以去看qt5的文档。

在Src目录下建立编译脚本build.sh
我编译使用的脚本

#!/bin/sh
echo 'build Qt5 for embedded linux Author Zhong Chen'
mkdir ~/Qt5.4.1/5.4/armlinux_armv7
$PWD/configure -v \
        -prefix /home/zeno/Qt5.4.1/5.4/armlinux_armv7/ \
        -confirm-license \
        -opensource \
        -release  \
        -make libs \
        -xplatform linux-arm-gnueabi-g++ \
        -pch \
        -qt-sql-sqlite \
        -qt-zlib \
        -qt-libjpeg \
        -qt-libpng \
        -qt-freetype
        -no-opengl \
        -no-sse2 \
        -no-openssl \
        -no-nis \
        -no-cups \
        -no-glib \
        -no-xcursor -no-xfixes -no-xrandr -no-xrender \
        -no-separate-debug-info \
        -no-phonon \
        -no-xkb -no-sm -no-xinerama -no-xshape \
        -no-qvfb -no-gfx-qvfb -no-kbd-qvfb -no-mouse-qvfb -qt-kbd-usb \
        -nomake examples -nomake tools
make -j2 && make install -j2

你可以详细的根据自己的需要配置,在文件夹下运行这个脚本就行。

4.添加 tslib 支持

为了使单点触摸屏可用,还需要编译Qt的tslib插件,查阅相关资料:
一般的开发板都会提供,仅需要在板子上设置TSLIB的环境变量,主要的几个变量如下:

#! /bin/sh
# "source" this file when wanna run a Qt application on the ARM Board.

###############  the below lines are for stardard TSLIB ##################
export TSLIB_ROOT=/opt/tslib
export TSLIB_CALIBFILE=$TSLIB_ROOT/etc/pointercal
export TSLIB_CONFFILE=$TSLIB_ROOT/etc/ts.conf
export TSLIB_PLUGINDIR=$TSLIB_ROOT/lib/ts
export TSLIB_TSDEVICE=/dev/touchscreen-1wire
#export TSLIB_TSDEVICE=/dev/input/event2

################  the below lines are optional ##############
#export TSLIB_FBDEVICE=/dev/fb0
#export TSLIB_CONSOLEDEVICE=none

此外还要修改 ts.conf文件:

#module_raw one_wire_ts_input
module_raw friendlyarm-ts-mtinput #使用友善提供的电容屏TSLIB插件。需要先将friendlyarm-ts-mtinput.so拷贝到TSLIB_PLUGINDIR目录中

module pthres pmin=1
module variance delta=30
module dejitter delta=100
module linear

到此为止 tslib 就基本能用了,首次使用时应先运行 ts_calibrate 进行触摸屏校准。我用的这个版本的tslib自带的ts_calibrate程序不太好用,所以我依然使用友善提供的ts_calibrate进行校准。

有了tslib后,进入Qt源码目录中的 “qtbase/src/plugins/generic/tslib/”,运行 qmake 生成 Makefile,并在Makefile中将tslib的头文件和库文件路径添加到编译链接选项中(-I /…tslib/include -L/…/tslib/lib);然后运行 make 和 make install即可。这时,Qt5安装目录的 “plugins/generic/”目录下就出现”libqtslibplugin.so”这个库文件了。

5.运行Qt程序
需要说明的是,Qt5.0开始,Qt自身不再单独实现窗口系统,QWS不复存在,取而代之的新机制是QPA(Qt平台抽象),QPA使得Qt对不同平台的支持变得更加灵活,当需要支持一个新平台时,只需为该平台编写一个QPA插件。

With the release of Qt 5.0, Qt no longer contains its own window system implementation: QWS is no longer a supported platform. For single-process use cases, theQt Platform Abstraction is a superior solution……参考 http://qt-project.org/doc/qt-5/embedded-linux.html

编译完Qt后,只需将生成的lib和plugins文件夹拷贝到开发板,另外,当在嵌入式Linux平台上运行应用程序前,应根据自己平台的实际情况提前设置好下面几个环境变量:

export QT_QPA_PLATFORM_PLUGIN_PATH=/opt/Qt-5.3.2/armv7-a/plugins/platforms
export QT_QPA_PLATFORM=linuxfb:tty=/dev/fb0
export QT_QPA_FONTDIR=/opt/Qt-5.3.2/armv7-a/lib/fonts
export QT_QPA_GENERIC_PLUGINS=tslib:/dev/touchscreen-1wire  #使用tslib插件

然后就可以运行Qt程序了

以前Qt4的程序在嵌入式Linux平台运行时,需要在命令行输入-qws选项以启动Qt窗口系统服务,如” ./HelloWorld -qws”;而使用Qt5后,不再需要-qws,而需要通过-platform来指定要使用的QPA插件,如” ./HelloWorld -platform linuxfb”,如果不指定,则用默认的QPA插件,默认的QPA插件通过上面的QT_QPA_PLATFORM变量指定。

关于Zeno Chen

本人涉及的领域较多,杂而不精 程序设计语言: Perl, Java, PHP, Python; 数据库系统: MySQL,Oracle; 偶尔做做电路板的开发,主攻STM32单片机
此条目发表在C/C++分类目录。将固定链接加入收藏夹。