需要word版本的同學可自行下載:點此下載
由於項目需要,領導要求實現Qt5的移植,目標板是imx6sx,且界面一定要炫酷.....好吧,既然要炫酷,當然要利用Qt的qml,然而qml又需要opengl的支持。
於是便開始了虐心的Qt5.6移植之旅,我的移植過程大體可以分爲三個階段,也是自己探索的過程。
第一階段,我嘗試手動移植opengl和Qt,然而需要的第三方庫數不勝數,且中間錯誤頻出,所以改變策略,進入第二階段
第二階段,使用yocto移植Qt5,yocto很好用,但是編譯時間比較長,大部分時間用來下載,但不管怎麼說,使用這種方法成功了,但是缺點是yocto的每一個版本只有一個QT版本,而yocto版本又是隨着內核版本更新的,比如最新版本的yocto源碼包含的是Qt5.5.1,而我要移植的是Qt5.6版本,原因有兩點,1、5.6是LTS版本,2、5.6版本比5.5版本多了一些我需要的控件,比如Qt.lab.controls中的drawer。我試過直接替換其中Qt源碼爲5.6版本,但是仍然是錯誤頻出。所以進入第三階段
第三階段,我使用yocto生成opengl等相關庫,然後再手動編譯Qt5.6,最終測試成功。
移植過程如下:
開發環境說明
操作系統:windows7 x64
宿主機:vmware10+Ubuntu14.04LTS32bit
目標機:i.mx6sx
使用工具說明
Yocto是一個開源社區,它通過提供模版、工具和方法幫助開發者創建基於linux內核的定製系統。具體的yocto使用方法請參考YoctoProject Quick Start。
Bitbake是yocto提供的構建工具,可以使用bitbake命令生成特定的鏡像、單獨編譯某一個模塊、清除生成的文件等等,它的功能類似於make。
Repo是Google用python腳本寫的調用Git的腳本,它與git的區別是,repo可以一次性從多個倉庫獲取資源到本地。
Linaro是由ARM、飛思卡爾、IBM、Samsung、ST-Ericsson 及德州儀器 (TI)等半導體廠商聯合創立的非營利性質的開源軟件公司。致力於開發不同半導體公司系統單芯片(SoC)平臺的共通軟件。在編譯Qt5的過程中,我們使用linaro提供的交叉編譯工具,經過測試4.6版本與3.10.17版本的sysroot可配合使用,4.6版本與4.1.15版本sysroot配合使用會出問題,找不到libc庫。4.8和4.9版本經過測試可以與4.1.15版本sysroot配合使用。目前linaro官方提供的最新版本是5.3版本,尚未測試。
依賴關係說明
Qt quick模塊需要opengl支持來生成libQt5OpenGL.so等相關庫文件,opengl庫由於涉及到gpu,所以又跟內核與設備樹息息相關,一個可用的opengl庫必須滿足兩點:1,可用於對應的目標機器 2、與對應的內核版本匹配。所以可以看到網上下載的gpu庫的命名格式爲gpu-viv-bin-machine-kernelVersion,例如:gpu-viv-bin-imx6q-3.10.17-1.0.0.tar.gz。
由上所述,我們可以知道,Qt5的移植也需要與內核版本保持一致,換句話說,更換內核版本後意味着要重新移植與之匹配的Qt5。
使用yocto移植Qt5過程說明
1、 安裝Ubuntu,也可以使用其他操作系統,但是yocto官方提供的手冊中都是以Ubuntu爲例,建議安裝Ubuntu14.04LTS版本,且最少分配100G的磁盤空間。安裝過程不做說明。
2、 安裝移植過程中Ubuntu系統所需要的軟件包
$ sudo apt-get installgawk wget git-core diffstat unzip texinfo gcc-multilib \
build-essential chrpath socat
$ sudo apt-get install libsdl1.2-dev xterm sed cvssubversion coreutils texi2html \
docbook-utils python-pysqlite2 help2man make gcc g++desktop-file-utils \
libgl1-mesa-dev libglu1-mesa-dev mercurialautoconf automake groff curl lzop asciidoc
$ sudo apt-get install u-boot-tools
3、 安裝repo
$ mkdir ~/bin
$ curlhttp://php.webtutor.pl/en/wp-content/uploads/2011/09/repo > ~/bin/repo
$ chmod a+x ~/bin/repo
$ export PATH=~/bin:$PATH
4、 同步yocto工程
$ mkdir fsl-release-bsp
$ cd fsl-release-bsp
$ git config --globaluser.name "Your Name"
$ git config --globaluser.email "Your Email"
$ git config --list
$ repo init -ugit://git.freescale.com/imx/fsl-arm-yocto-bsp.git -b imx-3.14.28-1.0.0_ga
$ repo sync
5、 配置構建選項
3.14.28版本
$ MACHINE=imx6qsabreauto sourcefsl-setup-release.sh –bbuild-fb –e fb
4.1.15版本
$ MACHINE=imx6qsabreauto sourcefsl-setup-release.sh –bbuild-fb DISTRO=fsl-imx-fb
如上所示,不同的yocto工程版本的配置命令略有不同,具體的命令需要參考對應版本源碼中的README文件。
6、 構建鏡像
$ bitbake fsl-image-qt5
其中fsl-image-qt5爲配方名稱,可以使用如下命令查看配方。
$ bitbake –s
這個命令會列出所有的配方,但是由於yocto支持的廠家不止飛思卡爾一家,所以顯示出來的配方會特別多,可以使用下面命令查找自己所需要的配方。
$ bitbake –s | grep qt 列出所有可生成qt的配方
$ bitbake –s | grep fsl 列出所有飛思卡爾處理器可使用的配方
$ bitbake –s | grep toolchain 列出所有工具鏈的配方
在構建的過程中可能會出現錯誤,一個通用的解決辦法是,先清除構建出問題的任務,然後再重新構建。
$ bitbake –c cleanall taskname
$ bitbake –c build taskname
$ bitbake fsl-image-qt5
由於構建鏡像的過程,多個包之間存在依賴關係,有時候生成的構建隊列的順序會有問題,比如A依賴B,但是在構建隊列中,A在B之前構建,這個時候A就會找不到B,從而出現錯誤,這種問題的解決辦法是,先清除A,然後手動構建B,然後再重新bitbake。但是前提是要了解他們之間的依賴關係。
$ bitbake –c cleanall A
$ bitbake –c build B
$ bitbake fsl-image-qt5
7、 上一步成功之後,官方提供的u-boot、zImage、rootfs就已經生成了,它們所在的路徑是:BUILDDIR/tmp/deploy/image/imx6sxsabresd/,在生成的文件系統中,已經包含了移植好的Qt5,且gpu需要的相關庫也已經生成。但是Qt開發還需要qmake,而qmake可以使用生成工具鏈相關的配方構建,執行下面命令:
$ bitbake fsl-toolchain-qt5
這個命令執行成功後,會在BUILDDIR/tmp/deploy/路徑下生成sdk目錄,執行sdk目錄下的腳本文件
$ sh BUILDDIR/tmp/deploy/sdk/xxxxxxxxx.sh
運行該腳本後,會在/opt目錄下生成工具鏈和qmake。
至此,使用yocto移植Qt5就已經完成了,如果對Qt版本以及內核版本沒有特殊要求的話,就可以使用上面生成的SDK來進行Qt應用程序的開發了。如果對於Qt版本以及內核版本有特殊要求的話,那麼就需要繼續完成下面的操作,來獲取你想要的版本,因爲yocto工程的每一個分支都提供一個確定版本的Qt配方,比如,如果你選擇使用4.1.15版本內核,那麼意味着你就必須使用Qt5.5.1版本,我曾嘗試過直接替換yocto工程Qt5層的配方,但是最終生成的鏡像對於字體沒有很好的支持,通過查閱資料,我瞭解到,同一層的所有配方最好是隸屬於同一分支,否則可能會出問題,甚至無法生成鏡像,因爲各層之間是互相關聯的,且yocto工程源碼、補丁衆多,想要修改配方文件亦無從下手。所以最好的方法是,使用yocto生成sysroot,然後使用生成的sysroot手動移植Qt5。
手動移植Qt5過程說明
1、 下載所需源碼,清單如下:
qt-everywhere-opensource-src-5.6.0.tar.gz
gcc-linaro-arm-linux-gnueabihf-4.9-2014.07_linux.tar.gz
2、 使用yocto獲取sysroot,根據自己的需要可自行選擇內核版本。此步驟在上面已經介紹過了,此處不做贅述,我們需要的sysroot的路徑爲:build/tmp/sysroots/machieName/
3、 解壓已經下載的qt源碼以及交叉編譯工具,將交叉編譯工具的路徑添加到PATH,並聲明CROSS_COMPILE。
exportCROSS_COMPILE=${cross compile dir}/bin/arm-linux-gnueabihf-
export PATH=${cross compile dir}/bin
4、 編輯qmake.conf,路徑在Qt源碼下qtbase/mkspecs/linux-arm-gnueabi-g++/qmake.conf,我的qmake.conf如下。
MAKEFILE_GENERATOR = UNIX
CONFIG += incremental
QMAKE_INCREMENTAL_STYLE= sublib
include(../common/linux.conf)
include(../common/gcc-base-unix.conf)
include(../common/g++-unix.conf)
QMAKE_LIBS_EGL += -lEGL
QMAKE_LIBS_OPENGL_ES2 += -lGLESv2 -lEGL -lGAL
QMAKE_LIBS_OPENVG += -lOpenVG -lEGL -lGAL
IMX6_CFLAGS = -march=armv7-a -mfloat-abi=hard-mfpu=neon -mtune=cortex-a9
QMAKE_CFLAGS += $$IMX6_CFLAGS
QMAKE_CXXFLAGS += $$IMX6_CFLAGS
DISTRO_OPTS+= hard-float
#Preferred eglfs backend
EGLFS_DEVICE_INTEGRATION= eglfs_viv
QT_QPA_DEFAULT_PLATFORM= eglfs
QMAKE_CFLAGS_RELEASE += -O2 $$QMAKE_CFLAGS
QMAKE_CXXFLAGS_RELEASE+= -O2 $$QMAKE_CXXFLAGS
#modifications to g++.conf
QMAKE_CC = arm-linux-gnueabihf-gcc
QMAKE_CXX = arm-linux-gnueabihf-g++
QMAKE_LINK = arm-linux-gnueabihf-g++
QMAKE_LINK_SHLIB = arm-linux-gnueabihf-g++
#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
#include(../devices/common/linux_arm_device_post.conf)
load(qt_config)
5、 配置Qt,我的配置如下:
./configure--prefix=/QtInstall -c++std c++11 -debug-and-release -qt-zlib -qt-libpng \
-xplatformlinux-arm-gnueabi-g++ -qt-freetype -fontconfig -no-directfb -qt-pcre \
-sysconfdir/QtInstall/sysconf -nomake tests -nomake examples -no-xcb -no-iconv \
-eglfs-opengl es2 -pkg-config \
-device-optionCROSS_COMPILE=/opt/crossCompile-linaro-4.9/gcc-linaro-arm-linux-gnueabihf-4.9-2014.07_linux/bin/arm-linux-gnueabihf-\
-sysroot/home/yocto/fsl-release-bsp/bld-fb/tmp/sysroots/imx6sxsabresd –v
其中字體配置部分選項,如果配置了fontconfig,那麼freetype則使用系統提供的庫,如果沒有配置fontconfig,則freetype可以配置爲-qt-freetype,即使用qt提供的freetype。但是qt5.6的官網文檔中特別指出:
Qt no longer ships anyfonts in thelib/fonts
directory. This means thatit is up to the platform (the system image) to provide the
necessary fonts.
這意味着Qt雖然提供字體支持,但是不再集成字庫到lib下。所以,爲了避免因此產生的影響,我們使用系統提供的字體支持,但是前提是你已經獲取了libfreetype.so。通常這些庫文件sysroot已經提供。
配置完成後,會有just run ‘make’的提示。我的配置結果如下:
Build options:
Configuration .......... accessibility alsa audio-backend c++11clock-gettime clock-monotonic compile_examples concurrent cross_compile dbusdbus-linked egl eglfs eglfs_gbm eglfs_viv enable_new_dtags evdev eventfdfontconfig full-config gbm getaddrinfo getifaddrs glib gstreamer-1.0 harfbuzzicu inotify ipv6ifname kms large-config largefile libudev linuxfb medium-configminimal-config mremap neon nis opengl opengles2 openssl openvg pcre pngposix_fallocate precompile_header pulseaudio qpa qpa reduce_exports releaserpath shared small-config system-freetype system-jpeg threadsafe-cloexecuse_gold_linker zlib
Build parts ............ libs
Mode ................... release
Using sanitizer(s)...... none
Using C++ standard ..... c++11
Using gold linker....... yes
Using new DTAGS ........ yes
Using PCH .............. yes
Using LTCG ............. no
Target compiler supports:
Neon ................. yes
Qt modules andoptions:
Qt D-Bus ............... yes (linked todbus-1)
Qt Concurrent .......... yes
Qt GUI ................. yes
Qt Widgets ............. yes
Large File ............. yes
QML debugging .......... yes
Use system proxies ..... no
Support enabledfor:
Accessibility .......... yes
ALSA ................... yes
CUPS ................... no
Evdev .................. yes
FontConfig ............. yes
FreeType ............... yes (system library)
Glib ................... yes
GStreamer .............. yes (1.0)
GTK theme .............. no
HarfBuzz ............... yes (bundled copy)
Iconv .................. no
ICU .................... yes
Image formats:
GIF .................. yes (plugin, usingbundled copy)
JPEG ................. yes (plugin, usingsystem library)
PNG .................. yes (in QtGui, usingbundled copy)
libinput................ no
Logging backends:
journald ............... no
syslog ............... no
mtdev .................. no
Networking:
getaddrinfo .......... yes
getifaddrs ........... yes
IPv6 ifname .......... yes
libproxy.............. no
OpenSSL .............. yes (loadinglibraries at run-time)
NIS .................... yes
OpenGL / OpenVG:
EGL .................. yes
OpenGL ............... yes (OpenGL ES 2.0+)
OpenVG ............... yes-auto
PCRE ................... yes (bundled copy)
pkg-config ............. yes
PulseAudio ............. yes
QPA backends:
DirectFB ............. no
EGLFS ................ yes
EGLFS i.MX6 ........ yes
EGLFS i.MX6 Wayland. no
EGLFS EGLDevice .... no
EGLFS GBM .......... yes
EGLFS Mali ......... no
EGLFS Raspberry Pi . no
EGLFS X11 .......... no
LinuxFB .............. yes
Mir client............ no
XCB .................. no
Session management ..... yes
SQL drivers:
DB2 .................. no
InterBase ............ no
MySQL ................ no
OCI .................. no
ODBC ................. no
PostgreSQL ........... no
SQLite 2 ............. no
SQLite ............... yes (plugin, usingbundled copy)
TDS .................. no
tslib .................. no
udev ................... yes
xkbcommon-x11........... no
xkbcommon-evdev......... no
zlib ................... yes (bundled copy)
NOTE: Qt is usingdouble for qreal on this system. This is binary incompatible against Qt 5.1.
Configure with'-qreal float' to create a build that is binary compatible with 5.1.
Qt is nowconfigured for building. Just run 'make'.
Once everythingis built, you must run 'make install'.
Qt will beinstalled into /QtInstall
Prior toreconfiguration, make sure you remove any leftovers from
the previous build.
需要確保opengl的選項是yes,否則無法運行QtQuick程序。
6、 編譯Qt。直接運行make,這個過程會出現一些錯誤,需要根據提示更改源碼,或安裝必要的軟件,編譯時間,不同的機器性能會有所差別,我的電腦編譯一次大約需要一下午。
7、 安裝Qt到配置目錄。直接運行make install,執行完成後,會在配置路徑下生成移植的Qt,內容如下:
8、 移植Qt。將生成的Qt目錄直接拷貝到文件系統目錄下,同時把sysroot下的icu相關的庫文件拷貝到文件系統的lib目錄下,因爲Qt程序依賴icu庫。拷貝完成後並不能直接運行Qt程序,還需要配置環境變量。我的配置腳本如下:
#!/bin/sh
export QTDIR=/QtInstall
exportQT_QPA_PLATFORM_PLUGIN_PATH=$QTDIR/plugins
exportQT_QPA_PLATFORM=eglfs:fb=/dev/fb0
exportQT_QPA_GENERIC_PLUGINS=evdevtouch:/dev/input/event1
exportQT_QPAFONTDIR=$QTDIR/lib/fonts
exportQML2_IMPORT_PATH=$QTDIR/qml
export LD_LIBRARY_PATH=$QTDIR/lib:/usr/lib:/lib:$LD_LIBRARY_PATH
export PATH=$QTDIR/bin:/bin:/usr/bin:/usr/bin/qt5:$PATH
執行完該腳本,就可以運行程序了。比如:
./QtDemo –platform eglfs
也可以:
qmlscene QtDemo.qml –platform eglfs
qmlscene用於執行一個qml文件。
至此,手動移植Qt完成,這種方法的優勢是,不在受限於內核版本,缺點是,每更換一次內核版本,就要重新編譯一次Qt。
附錄:燒寫u-boot、kernel、rootfs腳本
#!/bin/sh
echo image burn begin!
ORGSDCARD=`fdisk -l | awk'{if(($2=="/dev/sdb:")||($2=="/dev/sdc:")||($2=="/dev/sdd:")||($2=="/dev/sde:"))print $2;}'`
SDCARD=${ORGSDCARD%?}
FIR=1
SEC=2
SDCARDFIR=$SDCARD$FIR
SDCARDSEC=$SDCARD$SEC
echo--------------------------------------
echo ORGSDCARD = $ORGSDCARD
echo SDCARD = $SDCARD
echo SDCARDFIR = $SDCARDFIR
echo SDCARDSEC = $SDCARDSEC
echo--------------------------------------
echo '\n\n'
umount $SDCARDFIR
umount $SDCARDSEC
sync
dd if=/dev/zero of=$SDCARDbs=10M count=1
sync
fdisk $SDCARD << EOF
p
n
p
1
+20M
p
n
p
2
p
w
EOF
#上面的腳本對SD卡進行了分區
#燒寫uboot
ddif=/home/yocto/nfs/board/u-boot.imx of=$SDCARD bs=512 seek=2
#對分區1進行FAT格式化
mkfs.vfat $SDCARDFIR
#掛載分區1
mount $SDCARDFIR ./mount_point1
#複製設備樹文件到分區1
cp/home/yocto/nfs/board/imx6sx-sdb.dtb ./mount_point1
#複製內核代碼到分區1
cp /home/yocto/nfs/board/zImage./mount_point1
#複製M4內核代碼到分區1
#cp./imx6sx-image/hello_world.bin ./mount_point1
sync
#取消掛載
echo umount $SDCARDFIR !
umount ./mount_point1
sync
#對分區2進行EXT4格式化
mkfs.ext4 $SDCARDSEC
#掛載分區2
mount $SDCARDSEC ./mount_point2
#複製根文件系統到分區2
cp -a/home/yocto/nfs/board/rootfs/* ./mount_point2
sync
#取消掛載
echo umount $SDCARDSEC!
umount ./mount_point2
sync
echo image burn ok!