Skip to content

Instantly share code, notes, and snippets.

@uranusjr
Last active May 7, 2019 14:35
Show Gist options
  • Save uranusjr/91c0086109e6c35bbbe48a0b6a405f78 to your computer and use it in GitHub Desktop.
Save uranusjr/91c0086109e6c35bbbe48a0b6a405f78 to your computer and use it in GitHub Desktop.

Revisions

  1. uranusjr revised this gist Jun 27, 2016. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion rpi-qt5-cc.md
    Original file line number Diff line number Diff line change
    @@ -111,7 +111,7 @@ 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/qtproject/qt5.git`
    有些教學會用 `git://`,不過官方現在似乎是建議用 HTTPS。如果你連不上 code.qt.io(我有時候會),他們在 GitHub 上也有 mirror:`https://github.com/qt/qt5.git`

    ~~~
    cd qt5
  2. uranusjr revised this gist Jun 21, 2016. 1 changed file with 3 additions and 1 deletion.
    4 changes: 3 additions & 1 deletion rpi-qt5-cc.md
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,8 @@
    # 在 Ubuntu 16.04 為 Raspbian Jessie 交叉編譯 Qt 5.6 桌面版

    ## 筆記

    Qt 在 Raspberry Pi 上可以跑兩種版本
    Qt 在 Raspberry Pi 上可以跑兩種版本

    * 桌面版。你平常在 Linux 發行版裡看到的會是這個,包含 Raspbian 在內。通常基於 X11,就是個普通的 GUI 框架。
    * 嵌入版。這個版本不需要鐘面系統,通常是直接走 framebuffer 直接把東西畫到螢幕上,適合一些嵌入式設備的應用。
  3. uranusjr created this gist Jun 21, 2016.
    208 changes: 208 additions & 0 deletions rpi-qt5-cc.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,208 @@
    ## 筆記

    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 是 $512 \times 137216 = 70254592$。其他版本會不一樣,需要自己計算。

    ### 修復連結

    我們會需要修復一些 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
    ~~~

    ### 取得 Qt 原碼

    ~~~
    git clone https://code.qt.io/qt/qt5.git
    ~~~

    有些教學會用 `git://`,不過官方現在似乎是建議用 HTTPS。如果你連不上 code.qt.io(我有時候會),他們在 GitHub 上也有 mirror:`https://github.com/qtproject/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
    ~~~

    ### 編譯 Qt Base

    ~~~
    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 除了基本的模組之外,還有一些額外的選用元件。不過滿多在上面都已經一起編好了。為了你未來可能需要:

    1. `cd` 進去元件的目錄
    1. `$RPIQT/bin/qmake .`
    1. `make`
    1. `sudo make install`

    要注意的是有些元件會有 dependency,例如 Qt Declarative 會需要 QT JS Backend。有些元件會需要 OpenGL 的 header files,在這種狀況就會需要你先在 image 上先裝好,才能正確編譯。


    ### 拷貝 image 到 SD 卡

    這個大家應該都很熟了?

    ~~~
    cd $RPIROOT
    sudo umount rasp-pi-rootfs
    sudo dd bs=1M if=2016-05-27-raspbian-jessie.img of=/dev/sdb
    ~~~

    記得改 `of` 的 device name。