Ch2 Toolchain — Embedded System學習紀錄

張凱翔
7 min readJan 27, 2021

--

Toolchain

toolchain (工具鏈)就是一組工具集,能讓你的原始程式碼,編譯為可以在目標設標上運行的執行檔。這當中包括了一個編譯器、連結器以及執行期使用的函式庫。

然而你需要一組 toolchain 才能建立起embedded linux system的其他三項組成:bootloaderkernelroot file system。而且這組 toolchain 必須要能編譯以組合語言、C語言、C++語言所編寫的程式碼,因為這些是最基層的開源套件所使用的程式語言。

就一般而言,Linux 系統上所使用的 toolchain 都是基於 GNU專案 所發展的套件而來,而且至今大多數的開發情況都是如此。

然而 toolchain 又可以分為:

  1. native(原生):這類toolchain及其所產生的程式運行在同類型、有時甚至是同一部系統上。
  2. cross(跨平台):這類toolchain可以在與目標系統不同類型的作業系統上運行,這能讓開發工作在桌上型電腦完成、再載入到 embedded system 環境上進行測試。

crosstool-NG

數年前,Dan Kegel 為了產生跨平台的開發 toolchain,寫下一組指令集和建置檔,並稱其為 crosstool。直到 2007 年,Yann E. Morin則以此為參考,建立了次世代的 crosstool,也就是 crosstool-NG。直到今日,這是目前要從原始碼建立一個跨平台 toolchain 的最方便的方式。

開始安裝 crosstool-NG

我使用的作業系統為Ubuntu20.04;先下載 crosstool-NG 1.24.0 並解壓縮:

$ wget http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-1.24.0.tar.bz2
$ tar xjf crosstool-ng-1.24.0.tar.bz2

進入 crosstool-ng-1.24.0 資料夾後,進行安裝

$ cd crosstool-ng-1.24.0
$ ./configure --enable-local

其中參數 --enable-local 是讓程式安裝在目前資料夾。

$ make
$ make install

在 build 或是安裝過程中,可能電腦會缺少某些套件,請照著錯誤訊息進行安裝套件。

選擇 toolchain 並修改配置

我們假設目標環境是在使用 ARM Cortex A8 核心、有著VPFv3浮點運算器的Beagle Black上,然後使用最新版本的glibc。於是最接近的範本為arm-cortex_a8-linux-gnueabi。可以用show-這個前綴慈看到預設配置內容。

$ ./ct-ng show-arm-cortex_a8-linux-gnueabi

然後選擇目標環境

$ ./ct-ng arm-cortex_a8-linux-gnueabi
./ct-ng arm-cortex_a8-linux-gnueabi

使用 menuconfig 來修改配置,這些配置會存在.config檔案中。

$./ct-ng menuconfig

而這邊有幾點在配置上的變更

  1. 在Paths and misc的選項中,停用Rendor the toolchain read-only:
  2. 在Target option | Floating point裡,選擇hardware(FPU):主要目的是給有支援硬體浮點數運算元件的處理器架構,選擇最適化的浮點運算集。
  3. 在C-library | extra config中,增加 --enable-obsolete-rpc:是強我們產生出的toolchain去使用一個舊式的標頭檔-rpc.h,這個標頭檔在許多套件中仍會用到。

根據配置來下載、安裝、組件元件

$ ./ct-ng build

剖析toolchain

工具鏈的位置在~/x-tools/arm-cortex_a8-linux-gnueabihf/bin底下,將指令加入環境變數中:

$PATH=~/x-tools/arm-cortex_a8-linux-gnueabihf/bin:$PATH

寫一個 hello word 程式

並且進行編譯

$ arm-cortex_a8-linux-gnueabihf-gcc helloworld.c -o helloworld

接者可以使用 file 指令來將檔案的類型顯示出來;確認跨平台的方式編譯完成:

$ file helloworld 
file helloworld

SQLite 套件範例

某些套件可以輕易地以跨平台方式進行編譯,包括 Linux kernel、U-Boot、BusyBox。這邊將示範如何將 SQLite 套件加入至 toolchain library (sysroot)中。

SQLite函式庫是一個在嵌入式設備上廣受歡迎的關聯式資料庫實作;首先先下載SQLite開始:

$ wget http://www.sqlite.org/2015/sqlite-autoconf-3081101.tar.gz
$ tar xf sqlite-autoconf-3081101.tar.gz
$ cd sqlite-autoconf-3081101

接著執行腳本

$ CC=arm-cortex_a8-linux-gnueabihf-gcc
$ ./configure — host=arm-cortex_a8-linux-gnueabihf — prefix=/usr

其中 CC:C語言編譯器的指令、 --prefix=/usr:配置安裝的路徑。接者,注意到會有數個建置檔已經產生出來,可以開始使組建:

$ make

接者,你可以透過設定 make 指令 DESTDIR 變數,把它安裝到 toolchain 底下。如果不這樣做,會直接安裝在開發環境下的/usr目錄底下,這不是我要的。

$ make DESTDIR=$(arm-cortex_a8-linux-gnueabihf-gcc -print-sysroot) install

安裝完成後:你會發現有幾個檔案加進到 toolchain 的 sysroot 中:

  1. <sysroot>/usr/bin底下的sqlite3:這是SQLite的命令列介面,你可以在目標環上安裝及執行。
  2. <sysroot>/usr/bin底下的sqlite3:這是SQLite的命令列介面,你可以在目標環上安裝及執行。
  3. <sysroot>/usr/lib/pkconfig/sqlite3.pc:這些是套件配置檔。
  4. <sysroot>/usr/lib/include底下的sqlite3.h、sqlite3ext.h:這些是標頭檔。
  5. <sysroot>/usr/share/man/man1底下的sqlite3.1:這是操作手冊。

現在可以編譯那些有使用到sqlite3套件的程式。

補充 sysroot

這邊補充一下什麼是 sysroot:toolchain 的 sysroot資料夾底下,有存放函式庫、標頭檔和其他配置檔的子目錄。toolchain 的 --with-sysroot=配置參數,或者是透過命令列的 --sysroot=參數,就可以改變這項設定。可以透過-print-sysroot參數看到sysroot的預設位置。

而你會在sysroot底下找到這些東西:

  1. lib:裡面有C語言函式庫的共用物件,以及動態連結器/載入器ld-linux。
  2. usr/lib:裡面是C語言函式庫的靜態函式庫集合,以及其他後來才陸續安裝的函示庫。
  3. usr/include:這裡頭是所有函式庫要使用的標頭檔。
  4. usr/bin:這裡有目標環境上要執行的工具程式,如ldd指令。
  5. usr/share:用來做本地化與進行國際語言翻譯的。
  6. sbin:提供給ldconfig功能使用,用來最佳化載入函式庫路徑。

簡單來說,這裡某些東西是用來在開發環境上編譯程式,而其他東西(如共用函式庫和ld-linux)則是在目標環境執行期上所需要的。

--

--

張凱翔
張凱翔

Written by 張凱翔

Promote my knowledge by writing the medium

No responses yet