Back to Raspberry Pi Taiwan

【教學/進階】在個人電腦安裝 Raspberry Pi 的 Toolchain

Last Updated on 2023 年 3 月 12 日 by 小編

Raspberry Pi GCC PreBuilt ARM & AARCH64 Toolchains
圖片來源:Raspberry Pi GCC PreBuilt ARM & AARCH64 Toolchains

什麼是 Toolchain ?

Toolchain 是一套能讓你編譯、連結、除錯程式的軟體,例如 GCCLDGDBAS glibc 等。

x86 架構 vs. ARM 架構

假設我們寫了一個 hello.c 的程式要在個人電腦(Ubuntu)上執行,我們只要打 gcc hello.c 就可以將 hello.c 編譯成 x86 架構的可執行檔。由於 Raspberry Pi 上的處理器是 ARM 架構的,因此要將同樣的 hello.c 在 Raspberry Pi 執行,必須將程式編譯成 ARM 架構的可執行檔。

我們有兩個選擇,第一是直接在 Raspberry Pi 上編譯。第二是先在我們的個人電腦用 Raspberry Pi 的 toolchain 編譯完成後,再上傳到 Pi。

在個人電腦(Ubuntu)上 安裝 Raspberry Pi 的 toolchain

這篇簡介如何在個人電腦 安裝 Raspberry Pi 的 toolchain,以在 ubuntu 上安裝 gcc-linaro-arm-linux-gnueabihf-raspbian 為例。
 

step 1

在個人電腦安裝必要的套件

sosorry@ubuntu:~$ sudo apt-get install make git-core ncurses-dev

step 2

下載最新版的 toolchain

sosorry@ubuntu:~$ mkdir rpi
sosorry$ubuntu:~$ cd rpi
sosorry@ubuntu:~/rpi$ git clone https://github.com/raspberrypi/tools.git
remote: Reusing existing pack: 17273, done.
remote: Total 17273 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (17273/17273), 311.52 MiB | 343 KiB/s, done.
Resolving deltas: 100% (11698/11698), done.
Checking out files: 100% (15860/15860), done.

step 3

安裝 toolchain

安裝方法是將 gcc-linaro-arm-linux-gnueabihf-raspbian 加到環境變數裡。

sosorry@ubuntu:~/rpi$ vi ~/.bashrc
export PATH=$PATH:/home/sosorry/rpi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin   # add this line at the end of file

step 4

測試

先開啟一個新的終端機,輸入 arm 後連續按兩次 tab 鍵,如果跑出來一堆像下面的提示表示安裝成功。

arm-linux-gnueabihf-addr2line        arm-linux-gnueabihf-gcc              arm-linux-gnueabihf-gfortran         arm-linux-gnueabihf-objdump
arm-linux-gnueabihf-ar               arm-linux-gnueabihf-gcc-4.7.2        arm-linux-gnueabihf-gprof            arm-linux-gnueabihf-pkg-config
arm-linux-gnueabihf-as               arm-linux-gnueabihf-gcc-ar           arm-linux-gnueabihf-ld               arm-linux-gnueabihf-pkg-config-real
arm-linux-gnueabihf-c++              arm-linux-gnueabihf-gcc-nm           arm-linux-gnueabihf-ld.bfd           arm-linux-gnueabihf-ranlib
arm-linux-gnueabihf-c++filt          arm-linux-gnueabihf-gcc-ranlib       arm-linux-gnueabihf-ldd              arm-linux-gnueabihf-readelf
arm-linux-gnueabihf-cpp              arm-linux-gnueabihf-gcov             arm-linux-gnueabihf-ld.gold          arm-linux-gnueabihf-size
arm-linux-gnueabihf-elfedit          arm-linux-gnueabihf-gdb              arm-linux-gnueabihf-nm               arm-linux-gnueabihf-strings
arm-linux-gnueabihf-g++              arm-linux-gnueabihf-gdbtui           arm-linux-gnueabihf-objcopy          arm-linux-gnueabihf-strip

讓我們實際寫一個 hello.c 並編譯它吧。

sosorry@ubuntu:~/rpi$ vi hello.c
#include <stdio.h>
int main()
{
	printf("hello, world\n");
        return 0;
}

step 5

交叉編譯

用 Raspberry Pi 的 toolchain 編譯 hello.c。這一步驟稱為交叉編譯(cross-compiling)。

sosorry@ubuntu:~/rpi$ arm-linux-gnueabihf-gcc hello.c -o hello-arm

step 6

觀察檔案資訊

讓我們看看檔案的資訊,可以看到該檔案是 ARM 的格式。

sosorry@ubuntu:~/rpi$ file hello-arm
hello-arm: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.26, not stripped

如果我們在 x86 環境下試著執行會發現無法成功。

sosorry@ubuntu:~/rpi$ ./hello-arm 
bash: ./hello-arm: cannot execute binary file

step 7

上傳檔案到 Raspberry Pi

我們把 hello-arm 上傳到我們的 Pi,假設 IP 為 192.168.1.2。

sosorry@ubuntu:~/rpi$ scp hello-arm pi@192.168.1.2:/home/pi
pi@192.168.1.2's password: 
hello-arm                                                                                                                             100% 5447     5.3KB/s   00:00

在我們的 Pi 上執行,看看結果吧。

>pi@raspberrypi:~$ ./hello-arm
hello, world

 

常見問與答:

1. 為什麼要在個人電腦上安裝 toolchain?

因為個人電腦的處理速度通常高於 Raspberry Pi ,因此如果要開發比較大的專案(例如編譯核心),建議在個人電腦上處理,才不會等等等等。實務上在嵌入式系統的開發過程中,目標機器通常不會有 toolchain,因此常常會需要先在開發環境上將專案交叉編譯後再燒到目標機器。
 

2. 為什麼要安裝 gcc-linaro-arm-linux-gnueabihf-raspbian

因為在 userland README.md 告訴我們的。

This repository contains the source code for the ARM side libraries used on Raspberry Pi. These typically are installed in /opt/vc/lib and includes source for the ARM side code to interface to: EGL, mmal, GLESv2, vcos, openmaxil, vchiq_arm, bcm_host, WFC, OpenVG.

Use buildme to build. It requires cmake to be installed and an arm cross compiler. It is set up to use this one: https://github.com/raspberrypi/tools/tree/master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian

 

3. 如果個人電腦(主機端)是 64 位元的要裝那個版本的 toolchain?

要使用 tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin 目錄下的執行檔,也就是將該路徑加入環境變數即可。

Comments (13)

  • firmamenT Reply

    我在ubuntu 12.04上照著做,編譯完成後沒有任何錯誤訊息,也用file指令檢查過檔案內容,不過編出來的執行檔在pi上執行一直出現segmentation fault….程式的內容只是hello world,在pi上直接邊也可以用,有人可以給點建議我要需要檢查那些東西嗎?

    2014 年 5 月 16 日 at 下午 10:34
    • service Reply

      您的 gcc 版本是多少? 您可以下 -v 來查看版本,例如 arm-linux-gnueabihf-gcc -v
      另外,您可以下 ldd 查看動態連結的路徑是否正確,例如 ldd hello-arm

      2014 年 5 月 18 日 at 上午 12:42
      • firmamenT Reply

        我後來發現用32位元的UBUNTU就可以,反覆試了兩次(VM重灌UBUNTU,然後再重裝TOOL CHAIN)

        2014 年 8 月 24 日 at 上午 2:33
  • matt Reply

    我也遇到一模一樣的問題,我的ubuntu版本也是12.04
    gcc version是4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)
    我下ldd hello-arm指令出現的訊息是 – not a dynamic executable

    2014 年 5 月 19 日 at 下午 4:43
    • service Reply

      抱歉晚回覆了

      我們使用 amd64 的 Ubuntu 12.04 下測試可以正常編譯執行。以下是相關資訊,不知道您們的結果如何?

      在 Ubuntu 12.04 的 arm-linux-gnueabihf-gcc 版本:
      sosorry@vm:~$ arm-linux-gnueabihf-gcc -v



      gcc version 4.8.3 20140303 (prerelease) (crosstool-NG linaro-1.13.1+bzr2650 – Linaro GCC 2014.03)

      在 Pi 上檢查檔案型態:
      pi@raspberrypi ~ $ file hello-arm
      hello-arm: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.26, BuildID[sha1]=0x085ed5da85e33bd44825355f87554bb27b609d28, not stripped

      前述的 ldd 是在 Pi 所下的指令,非在 Ubuntu 下執行。
      在 Pi 檢查 shared library 的相依性:
      pi@raspberrypi ~ $ ldd hello-arm
      /usr/lib/arm-linux-gnueabihf/libcofi_rpi.so (0xb6f02000)
      libc.so.6 => /lib/arm-linux-gnueabihf/libc.so.6 (0xb6dc6000)
      /lib/ld-linux-armhf.so.3 (0xb6f10000)

      在 Pi 上直接編譯出的檔案使用 ldd 應該也是要和上方一樣的結果。

      2014 年 5 月 28 日 at 下午 10:38
      • steve Reply

        /usr/lib/arm-linux-gnueabihf/libcofi_rpi.so (0xb6f02000)
        libc.so.6 => /lib/arm-linux-gnueabihf/libc.so.6 (0xb6dc6000)
        /lib/ld-linux-armhf.so.3 (0xb6f10000)

        括弧裡的數字也要一樣嗎?

        gcc version 4.8.3 20140303 (prerelease) (crosstool-NG linaro-1.13.1+bzr2650 – Linaro GCC 2014.03)

        你的版本是4.8.3是在電腦上,但raspberryPi上應該還是4.6.3吧?

        2014 年 7 月 28 日 at 上午 11:22
  • dave Reply

    您好,請問gcc version 4.8.3 20140303 (prerelease) (crosstool-NG linaro-1.13.1+bzr2650 – Linaro GCC 2014.03) 這版本是在哪裡下載的?

    下載後又該如何替換成新版本呢?

    我打這指令 ldd hello-arm 後出現結果會跟你的一樣,但放到放到raspberry pi上還是會出現segmentation fault

    2014 年 7 月 28 日 at 上午 10:42
  • aloha Reply

    你好,我碰到的問題是用scp command 要把hello-arm 丟到樹梅派板上執行時,出現 permission denied, 請教一下各位,這是哪裏的問題? 先前有出現 一個ECDSA key 的問題,我選yes,繼續connect, 然後就被拒絕了

    2014 年 11 月 24 日 at 下午 7:58
    • service Reply

      您好

      遇到 permission denied,最有可能發生的問題是
      1. 檔案沒有執行權限,您可以用 chmod 755 將檔案擁有者的權限改為可執行。
      2. 使用者沒有執行檔案的權限,您可以用 chown pi:pi hello-arm 將檔案的擁有者和使用群組都改為 pi。

      遇到 ssh 連線的 key 有問題,通常是多台主機使用同一個 IP,只要將 ~/.ssh/known_hosts 裡面儲存 host 的 public key 給刪除就可以了。

      2014 年 11 月 25 日 at 下午 11:52
  • ken Reply

    如果用static linking應該就可了??

    2015 年 10 月 13 日 at 下午 9:09
  • Norris Reply

    非常詳盡的資訊,感謝分享。

    2016 年 4 月 8 日 at 下午 12:02
  • wenlung-yang Reply

    請問pi 1和pi 3 的cross compiler 是在同一包https://github.com/raspberrypi/tools.git 嗎?
    我build 出來的在pi 1可以跑 pi3 不行

    2016 年 6 月 22 日 at 上午 10:16
    • wenlung-yang Reply

      我找到問題, 因為pi 1 我是用ftp binary mode 傳輸, 而pi3 上是用了tftp ascii mode

      2016 年 6 月 30 日 at 下午 3:15

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

Back to Raspberry Pi Taiwan