樹莓派學習::qt5.6.0交叉編譯(armv8 64位).

Ubuntu16.04 x64環境下進行qt5交叉編譯(armv8)


背景

交叉編譯的作用

由於arm板子的性能有限,在性能強大的筆記本或者臺式電腦上進行程序的調試和編譯是很舒服的事情。當然,如果對速度沒有追求,大可以在開發板上直接apt-get install qtcreator  , qt4等來配置環境,直接在開發板上進行編程。

 

測試環境

(1)硬件設備

  •  msi筆記本,I7-4710H,16G內存
  • 樹莓派3b+,armv8(64位),16Gsd卡

(2)系統環境

  • 筆記本:ubuntu16.04 x64位
  • 樹莓派3b+:debian9 x64位 
  • 建議 :如果要交叉編譯 32位的程序,筆記本系統最好用32位,相反,如果要交叉編譯出64位程序,筆記本系統 用64位,這樣可以免去很多奇怪的報錯

(3)你的疑惑:

問:樹莓派官方並沒有出64位的系統,爲什麼我的樹莓派安裝的是64位系統

答:個人需求,具體安裝會在下文

 

環境配置 

一、樹莓派環境安裝

(1)64位系統映像下載:鏈接: https://pan.baidu.com/s/1T5kd8HHyuBYjRBJ-gKoiXQ 提取碼: vkgr 

系統來源:OPENFANS開源社區-量子云&&樹莓派愛好者基地。

(2) 系統燒寫

  • 像官方系統一樣燒寫即可

(3)系統配置

1)創建文件sudo nano /etc/network/interfaces.d/wlan0

  • 由於給出的系統是純淨系統,沒有ui界面,因此爲了可以連上ssh,儘量在有網絡的條件下進行
  • 開機即可使用ssh,關於有線網絡IP請自行在路由器上檢查。賬戶名:pi  密碼:raspberry
  • 下面給出wifi設置教程,個人估計可以在sd卡上直接寫入,那麼就可以直接連wifi,當然也可以在ssh下設置

2)編輯文件,寫入以下內容:

auto wlan0

allow-hotplug wlan0

iface wlan0 inet dhcp

wpa-ssid “你的無線SSID名稱”

wpa-psk “你的無線SSID對應的密碼”

3)保存退出

4)重啓或輸入sudo service networking restart即可正常使用

(4)安裝桌面

#教程推薦使用mate桌面環境,個人也是用這個,希望有小夥伴嘗試一下gnome,再來分享

sudo apt-get update

sudo apt-get install xserver-xorg -y 

sudo apt-get install mate-desktop-environment-core lightdm -y

重啓之後即可看到久違的桌面 

 

二、筆記本ubuntu系統安裝(不展開)

  • 請確保你的系統比較乾淨
  • 系統要進行update和upgrade

三 、 配置筆記本下的交叉編譯環境

(1)問答:

問:什麼交叉編譯環境?

答:就是配置一個對應平臺的g++編譯器,比如說上面安裝的樹莓派3b+ 的64位系統,那麼就要配置一個aarch64或arm64的g++編譯器。

問:如何查看系統架構平臺?

答:輸入uname -a,如果有x86_64的就是64位,還可能出現arm64  aarch64等字樣。其他自行查資料

問:如何配置這個g++編譯器?

答:看下文

(2)對應平臺的g++編譯器配置,即配置交叉編譯器

1)檢查系統架構平臺:uname -a

2)下載交叉編譯器aarch64-linux-gnu-gcc

這裏有舊版的和新版的可選,網上一片教程都用的舊版,個人用的是新版

舊版下載: 鏈接: https://pan.baidu.com/s/1tMFvsea1EFUxBx_K1u6BYg 提取碼: xwpy 

新版下載:https://releases.linaro.org/components/toolchain/binaries/7.3-2018.05/aarch64-linux-gnu/

3) 配置這個交叉編譯器

新建一個文件夾arm,解壓:

 4)將路徑寫入PATH路徑中,即打開文件:

sudo vim /etc/profile

5)在添加剛剛解壓的文件夾的bin路徑到PATH,即添加如下內容(具體路徑自行根據環境修改):

export PATH=$PATH:/home/用戶名/arm/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/

6)刷新:

source /etc/profile

7)檢查配置是否完成(注意,兩個都需要有正常輸出,這一步纔算完成):

aarch64-linux-gnu-g++ -v
sudo aarch64-linux-gnu-g++ -v

 正常來說應該有如下輸出:

特殊情況有:

輸入sudo aarch64-linux-gnu-g++ -v,提示沒有找到命令,而直接輸入aarch64-linux-gnu-g++ -v可正常顯示

解決方案:在sudos配置文件下把交叉編譯器的bin路徑也加入

sudo vi /etc/sudoers

加入之後應該是這個樣子:

這時再次輸入sudo aarch64-linux-gnu-g++ -v,就應該可以正常輸出版本信息了。

問:爲什麼一定要sudo aarch64-linux-gnu-g++ -v 也有正常輸出?

答:因爲在下面的編譯過程中make中沒有用到sudo,但是安裝的時候要sudo make install,這一步的操作也需要交叉編譯器,如果不正確配置,會出現make成功,而sudo make install失敗的奇觀。

(3)到這裏,這個交叉編譯環境就基本OK了

 

四、下載qt源碼以及安裝包

(1)問答:

問:爲什麼需要源碼和安裝包兩個東西?

答:安裝包是用來給本地裝一個qt,源碼是用來編譯一個 對應平臺的qt,即編譯一個arm平臺可用的qt

問:QT版本有要求嗎?

答:這個qt版本的話就有點講究了,個人在QT5.5的源碼交叉編譯中出現莫名其妙的錯誤,QT5.7的話版本有點新,沒有嘗試,最終利用QT5.6.0版本成功編譯,所以推薦QT5.6.0

(2) 下載

安裝包下載:http://download.qt.io/archive/qt/5.6/5.6.0/

源碼下載:http://download.qt.io/archive/qt/5.6/5.6.0/single/

(3)利用安裝包在本地安裝

這個比較簡單,一路next基本沒問題

 

(4)依賴庫安裝:

sudo apt-get install qt5*-dev
sudo apt-get install qtbase5-dev
sudo apt-get install qtdeclarative5-dev qml-module-qtquick-controls

 

五、qt源碼配置

(1)問答:

問:這個qt源碼怎麼用?

答:我們的目的是利用源碼編譯出一個arm平臺的qt,所以需要先配置,然後編譯

(2)編譯平臺信息配置

1)解壓下載的源碼包,路徑沒要求,一般在“/home/用戶” 下就可以

2)進解壓的文件夾瀏覽一番

3)找到qtbase,這個是編譯出來的文件存放地方

cd qtbase

4)在qtbase中找到mkspecs文件夾 ,這個文件夾放置着各種平臺下的編譯配置信息,

cd mkspecs

5)在mkspecs文件夾中找到 linux-arm-gnueabi-g++文件夾,這個看起來就跟我們的平臺很像,進入瀏覽

cd linux-arm-gnueabi-g++

 6)在 linux-arm-gnueabi-g++文件夾下,可以看到兩個文件,其中qmake.conf是我們需要修改的文件

 7)qmake.conf原內容:

#
# qmake configuration for building with arm-linux-gnueabi-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                = arm-linux-gnueabi-gcc
QMAKE_CXX               = arm-linux-gnueabi-g++
QMAKE_LINK              = arm-linux-gnueabi-g++
QMAKE_LINK_SHLIB        = arm-linux-gnueabi-g++

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

8)修改:我們需要將原內容的arm-linux-gnueabi交叉編譯器換成我們的,所以直接將上面的arm-linux-gnueabi換成aarch64-linux-gnu即可,當然,如果你下載的是其他交叉編譯器,換成你對應的平臺交叉編譯器即可。如果不知道如何修改,可在終端上輸入aarch64-linux-gnu-gcc -v,來看信息,然後用Target:後面的內容替換上面原內容中的arm-linux-gnueabi即可。

9)修改後的qmake.conf文件內容如下:

#
# qmake configuration for building with arm-linux-gnueabi-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
load(qt_config)

10)到這裏,配置的第一步完成了

(3)編譯選項配置

1)這個就有點玄妙了 ,建議先閱讀文章:[編譯] QT編譯./configure參數的詳細解釋[新手充電必讀]

2)總的來說,就是通過./configure 後面加上我們的目標平臺信息、要編譯的庫、不編譯的庫等一些列選項,來編譯出一個我們需要的arm目標平臺版本的qt

3)一些關鍵選項:

-prefix  後面填入編譯安裝後arm平臺版本的qt路徑(後面需要將這個qt複製到開發板)

-xplatform linux-arm-gnueabi-g++  這裏就是選擇我們剛剛修改完的目標平臺信息,編譯將會以這個目標平臺爲編譯的目標

-no-pch、-no-iconv這幾個no表示不編譯這幾個庫,因爲編譯他們可能會導致奇怪的錯誤

-skip qtdeclarative 表示不編譯qml、quick庫,因爲這兩個庫需要opengl庫支持,這個問題的描述相關參考:

      1、https://blog.csdn.net/hhhlizhao/article/details/73604445

      2、http://www.qter.org/forum.php?mod=viewthread&tid=5563&extra=&ordertype=1

      3、https://www.qtcentre.org/threads/55438-Project-ERROR-Unknow-module(s)-in-QT-quick

      4、https://bugreports.qt.io/browse/QTBUG-32740

4)這裏直接給出一個.sh文件,裏面直接寫好了一些選項,一般不建議新手進行修改

#!/bin/sh  
./configure -prefix /home/msi/arm/qt560_64/qt_sdk \
-opensource \
-release \
-no-pch \
-confirm-license \
-xplatform linux-arm-gnueabi-g++ \
-qt-zlib \
-no-iconv \
-no-gif \
-no-nis \
-qt-libjpeg \
-no-opengl \
-skip qtdeclarative \
-skip qtquickcontrols \
-skip qtquickcontrols2 \
-no-qml-debug \
-no-cups \
-no-glib \
-no-dbus \
-no-rpath \
-no-sse2 -no-sse3 -no-ssse3 -no-sse4.1 -no-sse4.2 \
-no-avx  \
-no-openssl \
-nomake tools \
-qreal float \
-qt-libpng \
-nomake examples

5)在qt源碼根目錄下,新建一個autoconfig.sh文件,將上面的內容複製到裏面。

 (警告:上面內容每一行最後,即'\'的後面不能有空格,否則會運行報錯)

gedit autoconfig.sh

6)賦權限

sudo chmod +x autoconfig.sh

7)運行,進行編譯前的配置

./autoconfig

8)沒有意外的話,輸出如下:

Running configuration tests (phase 1)...
Done running configuration tests.
Creating qmake...
.........................................................................................Done.
Running configuration tests (phase 2)...
Warning: Disabling pkg-config since PKG_CONFIG_LIBDIR is not set and
the host's .pc files would be used (even if you set PKG_CONFIG_PATH).
Set this variable to the directory that contains target .pc files
for pkg-config to function correctly when cross-compiling or
use -pkg-config to override this test.
Warning: Disabling pkg-config since PKG_CONFIG_SYSROOT_DIR is not set.
Set this variable to your sysroot for pkg-config to function correctly when
cross-compiling or use -pkg-config to override this test.
Done running configuration tests.

   Configure summary

Building on:   linux-g++ (x86_64, CPU features: mmx sse sse2)
Building for:  linux-arm-gnueabi-g++ (arm64, CPU features: neon)
Platform notes:

            - Also available for Linux: linux-clang linux-kcc linux-icc linux-cxx
        
Build options:
  Configuration .......... accessibility audio-backend c++11 c++14 c++1z clock-gettime clock-monotonic compile_examples concurrent cross_compile enable_new_dtags evdev eventfd freetype full-config getaddrinfo getifaddrs harfbuzz inotify ipv6ifname large-config largefile linuxfb medium-config minimal-config mremap neon no-gif no-pkg-config pcre png posix_fallocate qpa qpa reduce_exports release shared small-config threadsafe-cloexec use_gold_linker zlib 
  Build parts ............  examples libs
  Mode ................... release
  Using sanitizer(s)...... none
  Using C++ standard ..... c++1z
  Using gold linker....... yes
  Using new DTAGS ........ yes
  Using PCH .............. no
  Using LTCG ............. no
  Target compiler supports:

Qt modules and options:
  Qt D-Bus ............... no
  Qt Concurrent .......... yes
  Qt GUI ................. yes
  Qt Widgets ............. yes
  Large File ............. yes
  QML debugging .......... yes
  Use system proxies ..... no

Support enabled for:
  Accessibility .......... yes
  ALSA ................... no
  CUPS ................... no
  Evdev .................. yes
  FontConfig ............. no
  FreeType ............... yes (bundled copy)
  Glib ................... no
  GStreamer .............. no
  GTK theme .............. no
  HarfBuzz ............... yes (bundled copy)
  Iconv .................. no
  ICU .................... no
  Image formats: 
    GIF .................. no
    JPEG ................. yes (plugin, using bundled copy)
    PNG .................. yes (in QtGui, using bundled copy)
  libinput................ no
  Logging backends: 
    journald ............... no
    syslog   ............... no
  mtdev .................. no
  Networking: 
    getaddrinfo .......... yes
    getifaddrs ........... yes
    IPv6 ifname .......... yes
    libproxy.............. no
    OpenSSL .............. no
  NIS .................... no
  OpenGL / OpenVG: 
    EGL .................. no
    OpenGL ............... no
    OpenVG ............... no
  PCRE ................... yes (bundled copy)
  pkg-config ............. no 
  PulseAudio ............. no
  QPA backends: 
    DirectFB ............. no
    EGLFS ................ no
      EGLFS i.MX6 ........ no
      EGLFS i.MX6 Wayland. no
      EGLFS EGLDevice .... no
      EGLFS GBM .......... no
      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, using bundled copy)
    TDS .................. no
  tslib .................. no
  udev ................... no
  xkbcommon-x11........... no
  xkbcommon-evdev......... no
  zlib ................... yes (bundled copy)

Info: creating super cache file /home/msi/qt-everywhere-opensource-src-5.6.0/.qmake.super

Qt is now configured for building. Just run 'make'.
Once everything is built, you must run 'make install'.
Qt will be installed into /opt/arm/qt560_64/qt_sdk

Prior to reconfiguration, make sure you remove any leftovers from
the previous build.

9)頭文件修改:

修改qtimageformats/src/3rdparty/libwebp/src/dsp/dsp.h文件: 

//#define WEBP_USE_NEON //註釋第68行後就可以編譯通過

否則,在接下來的make &&make install過程中會出現如下錯誤:

.obj/disk3/myown/qt-5.6/qtimageformats/src/3rdparty/libwebp/src/dsp/dec.o:dec.c:function VP8DspInit: error: undefined reference to ‘VP8DspInitNEON’ 
.obj/disk3/myown/qt-5.6/qtimageformats/src/3rdparty/libwebp/src/dsp/enc.o:enc.c:function VP8EncDspInit: error: undefined reference to ‘VP8EncDspInitNEON’ 
.obj/disk3/myown/qt-5.6/qtimageformats/src/3rdparty/libwebp/src/dsp/lossless.o:lossless.c:function VP8LDspInit: error: undefined reference to ‘VP8LDspInitNEON’ 
.obj/disk3/myown/qt-5.6/qtimageformats/src/3rdparty/libwebp/src/dsp/upsampling.o:upsampling.c:function WebPInitUpsamplers: error: undefined reference to ‘WebPInitUpsamplersNEON’ 
collect2: error: ld returned 1 exit status

10)編譯文件修改:

修改/home/msi/qt-everywhere-opensource-src-5.6.0/qttools/src/src.pro

將SUBDIRS += linguist \  下面一行的qdoc刪除,刪除後的效果如下:

否則,在接下來的make &&make install過程中會出現(原因是qdoc這個包裏面用到 qml,而我們在選項-skip qtdeclarative 設置了不編譯qml,所以不刪除這個qdoc會報錯Project ERROR: Unknown module(s) in QT: qmldevtools-private):

cd qdoc/ && ( test -e Makefile || /home/msi/qt-everywhere-opensource-src-5.6.0/qtbase/bin/qmake /home/msi/qt-everywhere-opensource-src-5.6.0/qttools/src/qdoc/qdoc.pro -o Makefile ) && make -f Makefile install
Project ERROR: Unknown module(s) in QT: qmldevtools-private
Makefile:188: recipe for target 'sub-qdoc-install_subtargets' failed
make[2]: *** [sub-qdoc-install_subtargets] Error 3
make[2]: Leaving directory '/home/msi/qt-everywhere-opensource-src-5.6.0/qttools/src'
Makefile:56: recipe for target 'sub-src-install_subtargets' failed
make[1]: *** [sub-src-install_subtargets] Error 2
make[1]: Leaving directory '/home/msi/qt-everywhere-opensource-src-5.6.0/qttools'
Makefile:529: recipe for target 'module-qttools-install_subtargets' failed
make: *** [module-qttools-install_subtargets] Error 2


五、開始編譯

(1)make

make -j4

經過相當長時間後,大概半小時,make完成,輸出如下:

 (2)make  install

sudo make install

沒報錯的話,大概最後就這樣,就算編譯完成了

 

六、配置剛剛編譯的對應平臺qmake

(1)打開qtcreator

(2)點擊選項,選擇構建和運行

(3)選擇編譯器頁面

1)點擊右側的添加:選擇gcc

2)將路徑設置爲我們的交叉編譯器aarch64-linux-gnu的路徑 ,比如我的是:

3)添加完成,點應用

(4)選擇Qt Versions頁面

1)點擊 右側的添加

2)選擇我們剛剛編譯之前的配置選項--prefix路徑的bin文件夾下的qmake,即armv8平臺下的qmake

3)添加完成,點應用 

(5) 選擇構建套件(kit)頁面

1)點擊 右側添加

2)在編譯器下拉列表框中選上我們剛剛添加的aarch64-linux-gnu-gcc/  g++ 編譯器

3)在qt版本下拉列表框中選上我們剛剛添加的armv8的qt版本

4)kit配置完成如下

七、測試

(1)新建一個Qwidget項目

(2)在構建中選上剛剛添加的構建套件kit

(3)構建

(4)到構建的目錄中查看文件類型

輸入命令 

file 文件名

輸出如下(表明是arm64平臺的可執行文件 ):

 

八、開發板環境配置

(1)將上面ubuntu下編譯qt是的編譯選項--prefix 後的路徑,這個文件夾複製到開發板上

我的路徑如下:/home/msi/arm/qt560_64

複製到樹莓派下:/home/pi/qt560_64

(2)開發板qt庫路徑配置

 配置Qt的運行時環境,打開/etc/profile,在最後一行輸入一下內容:

export QTDIR=/home/pi/qt560_64/qt_sdk    #qtsdk在系統上的路徑
export QT_QPA_FONTDIR=$QTDIR/lib/fonts 
export QT_QPA_PLATFORM_PLUGIN_PATH=$QTDIR/plugins/ 
export LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH 
export QT_QPA_PLATFORM=linuxfb:fb=/dev/fb0    #framebuffer驅動
export QWS_MOUSE_PROTO=/dev/input/event0

(3)刷新

source /etc/profile

 九、開發板測試

(1)將我們剛剛在筆記本ubuntu系統下新建的Qwidget工程編譯出來的release文件夾複製到開發板上

(2)運行

(3)如果提示缺少類似libqtWidget.so.5.6等,在開發板上輸入apt-get install qt5-default,將一些缺失的共享庫補上就行

(4)運行效果 如下:


 十、總結

  • qt交叉編譯是一個噩夢
  • 儘量使用高版本的qt,儘可能減少報錯
  • 個人採用ubuntu16.04 X64+gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu + QT5.6.0 的交叉編譯過程如上
  • 有網友採用ubuntu16.04 +gcc-linaro-aarch64-linux-gnu-4.9-2014.07_linux +QT5.6.0也編譯成功 ,該文章如下:
  • https://blog.csdn.net/kaychangeek/article/details/80258464
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章