Qt 在 Raspberry Pi 上可以跑兩種版本:
- 桌面版。你平常在 Linux 發行版裡看到的會是這個,包含 Raspbian 在內。通常基於 X11,就是個普通的 GUI 框架。
- 嵌入版。這個版本不需要鐘面系統,通常是直接走 framebuffer 直接把東西畫到螢幕上,適合一些嵌入式設備的應用。
這個教學會編譯桌面版,因為我對這個版本比較熟。我上次試的時候 OpenGL 在 embedded 版還有些問題,不過 Qt 在那之後有很多更新,狀況應該會好很多。Qt 官方 wiki 也有個相關的教學:
https://wiki.qt.io/RaspberryPi2EGLFS
我是用虛擬機裝 Ubuntu 來編譯,如果你想做類似的事情,可能也會碰到這些問題,順便題一下。預設的虛擬機設定不太夠,我第一次編沒多久硬碟空間就用完了,double 重來結果在 linker 遇到記憶體不足直接 crash。
我最後成功的設定是 50 GB 空間與 2 GB RAM。應該是不用這麼多啦,不過編 Qt 實在很麻煩,安全至上。
我主要是參考 Qt wiki 裡的教學來做,然後不需要的略過,出問題再小改。原本的文章:
https://wiki.qt.io/RaspberryPi_Beginners_Guide
更新系統,然後安裝 Git,之後用來抓工具和 Qt 源碼會用到。
sudo apt update
sudo apt upgrade
sudo apt install git
我這裡把所有東西裝在 ~/rpi
,當然你可以改,把環境變數換掉就好了。
export RPIROOT=$HOME/rpi
export RPIIMG=$RPIROOT/rasp-pi-rootfs
export RPIQT=$RPIROOT/qt5pi
mkdir $RPIROOT
cd $RPIROOT
我這裡只有把 PATH
加到 active shell session。如果你希望預設就讀入,就要把它寫入 ~/.bashrc
之類的。我個人是習慣寫到 .env
之類的檔案,只在需要的時候 source。
這個可能有人早已經有了,就可以跳過。可以參考 Sosorry 的教學:
https://www.raspberrypi.com.tw/405/using-a-cross-compiler-for-raspberry-pi/
git clone https://github.com/raspberrypi/tools.git
export PATH=$PATH:$RPIROOT/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin
注意 cross compiler 有分 32- 和 64-bit。這年頭大部分人都裝 64-bit OS,你應該也是。如果你的作業系統是 32-bit,就把 PATH
路徑裡的 -x64
拿掉。
wget http://downloads.raspberrypi.org/raspbian_latest -O jessie-raspbian-latest.zip
unzip jessie-raspbian-latest.zip
mkdir $RPIIMG
sudo mount -t ext4 -o loop,offset=70254592 2016-05-27-raspbian-jessie.img $RPIIMG
注意:根據你的 image 版本不同,mount 的參數也要改變。其他的應該很容易理解,只有 offset 比較麻煩。如果你直接看這個 image 的 filesystem 結構:
$ fdisk -l 2016-05-27-raspbian-jessie.img
Disk 2016-05-27-raspbian-jessie.img: 3.8 GiB, 4019191808 bytes, 7849984 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x14c20151
Device Boot Start End Sectors Size Id Type
2016-05-27-raspbian-jessie.img1 8192 137215 129024 63M c W95 FAT32 (LBA)
2016-05-27-raspbian-jessie.img2 137216 7849983 7712768 3.7G 83 Linux
會看到這個 image 包含兩個分割。第一個分割是 bootloader,後面的則是 foot filesystem。我們要 mount 的是第二個,所以必須找到它的 offset。根據上面的資訊,一個 sector 是 512 bytes,所以這個 image 的 offset 是
我們會需要修復一些 relative links。比較方便的辦法是用別人提供的工具,但很可惜似乎沒有官方來源,只有一些口耳相傳的載點。
確認你有安裝好前面的 cross-compiling toolchain,並把它加入 PATH
。可以用
which arm-linux-gnueabihf-gcc
檢查。
下載並執行 symlink 修復工具
wget https://raw.githubusercontent.com/riscv/riscv-poky/master/scripts/sysroot-relativelinks.py
sudo python sysroot-relativelinks.py $RPIIMG
git clone https://code.qt.io/qt/qt5.git
有些教學會用 git://
,不過官方現在似乎是建議用 HTTPS。如果你連不上 code.qt.io(我有時候會),他們在 GitHub 上也有 mirror:https://github.com/qt/qt5.git
。
cd qt5
git checkout v5.6.1
你可以在這個階段選擇想要 compile 的版本。如果沒有 checkout 會編譯 dev HEAD,如果想要尖端科技可以試試,不過通常是會爆炸,別說我沒警告你。
可以用 git tag
看看有什麼版本可以用。
BTW 上週出了 Qt 5.7 不過我還沒試。
./init-repository
這個指令會自動載入這個版本的 Qt 元件源碼。注意這會需要一段時間,而且需要穩定網路連線。
如果有東西載到一半失敗,可能會讓你的 repository 處在一個很奇怪的狀態。這時候可以強迫重載:
./init-repository -f
cd $RPIROOT/qt5
./configure -opengl es2 -device linux-rasp-pi-g++ -device-option CROSS_COMPILE=$(which arm-linux-gnueabihf-gcc | sed 's/.\{3\}$//') -sysroot $RPIIMG -opensource -confirm-license -optimized-qmake -reduce-exports -release -no-qml-debug -make libs -make examples -prefix /usr/local/qt5pi -hostprefix $RPIQT
如果你用 Raspberry Pi 2,把 device 改成 linux-rasp-pi2-g++
。我在編譯時發現 QML 的 debug class 有用到 RPi 不支援的功能,所以用 -no-qml-debug
把它關了,幸好不重要。
這個指令裡面很多路徑是要對應到你自己 host machine 的設定。我這裡是根據前面設定的 $RPIROOT
變數,你的需求可能不同。唯一例外是 -prefix
參數,這是對應到 RPi 上的路徑,當然也是可以改,不過如果你沒有經驗,建議就用這個設定。
如果你要自己改設定,記得把 -opengl es2
設定加上去,才會有合適的 OpenGL backend 可用。有些時候你可能會想額外 compile 其他東西,就自己加吧。例如如果你想要 PostgreSQL plugin,就加上 -plugin-sql-psql
。下面的指令可以查看能用的選項:
./configure -help
我在這裡為了示範,所以編譯了 Qt 內建的範例程式。你之後自己編譯的時候應該不會用到,就把 -make examples
拿掉即可。
注意這裡我們選擇了開源版,並且同意了 Qt 的版權宣告。如果你想用商業版,請自己把選項換掉。
Configure 完成之後會出現一個表格,可以用來檢查你將要什麼。想修改的話,必須先清理 repository:
git submodule foreach --recursive "git clean -dfx"
再重新 configure。
接著就是正式開始 compile:
make
這個指令會跑非常非常久,如果你是在晚上做這件事情,直接去睡覺會是個好主意。想平行編譯的話可以試試 make -j4
之類的,不過我實測好像會踩到 GCC 的 bug 然後 crash。反正單純 make
應該不會有問題。
如果 make 到一半掛了想重來,可以先 make clean
清除原本 build 到一半的狀態。
make install
這樣就會把編譯完成的 Qt 安裝到 host machine 與 RPi image。這會裝到 -hostprefix
以及 image 的 filesystem root 加上 -prefix
指定的地方,例如上面的指令就是 ~/rpi/qt5pi
(host)與 ~/rpi/rasp-pi-rootfs/usr/local/qt5pi
。視情況根據權限加上 sudo
執行。
Qt 除了基本的模組之外,還有一些額外的選用元件。不過滿多在上面都已經一起編好了。為了你未來可能需要:
cd
進去元件的目錄$RPIQT/bin/qmake .
make
sudo make install
要注意的是有些元件會有 dependency,例如 Qt Declarative 會需要 QT JS Backend。有些元件會需要 OpenGL 的 header files,在這種狀況就會需要你先在 image 上先裝好,才能正確編譯。
這個大家應該都很熟了?
cd $RPIROOT
sudo umount rasp-pi-rootfs
sudo dd bs=1M if=2016-05-27-raspbian-jessie.img of=/dev/sdb
記得改 of
的 device name。
謝謝您的tutorial!!
不過我在編譯Qt Base的部份時,完成編譯後得到了以下的error:
The OpenGL ES 2.0 functionality test failed!
You might need to modify the include and library search paths by editing
QMAKE_INCDIR_OPENGL_ES2, QMAKE_LIBDIR_OPENGL_ES2 and QMAKE_LIBS_OPENGL_ES2 in
/home/seanlai/rpi/qt5/qtbase/mkspecs/devices/linux-rasp-pi2-g++
我是使用ubuntu 16.04 交叉編譯的pi 為raspberry pi2, 請問有什麼方法可以解決呢?
謝謝您.