Gentoo Linux 除了是一套非常強大、易於客製化的 Linux 系統以外,他亦可以讓你輕鬆的建 構不同平台的 toolchain,本文將介紹 Gentoo Linux 的 crossdev 套件,以及如何透過 crossdev 命令建立出不同平台的 toolchain.
Toolchain 中譯為 交叉工具鏈
,是在進行嵌入式開發必備的工具,包含了以下幾部份:
binutils
用來生成二進制(binary)文件的基本工具
gcc
GNU C/C++ 編譯器
gdb
GNU 除錯工具
glibc/ulibc/newlib
系統相關 C 語言函式庫
linux headers
僅在編譯 Linux 相關平台所需要,為 Linux Kernel 相關的 header files(頭文件)
在非 Gentoo Linux 的平台,一般我們都使用 crosstool-ng 來協助產生需要的開發環境, 但是對於 Gentoo Linux 而言,使用內建的 crossdev 套件即可以快速構件所需要的開發環 境。
要使用 crossdev,首先我們當然是要安裝他囉,在 Gentoo 下使用 emerge 命令進行安裝
Gentoo kernel # emerge sys-devel/crossdev
安裝完成後,我們可以使用 crossdev -t help
查看 crossdev 支援哪些平台
Gentoo kernel # crossdev -t help Supported Architectures: - alpha - arm / armeb / aarch64 - hppa (parisc) - ia64 - i386 / i486 / i586 / i686 (x86) - m68k - mips / mipsel / mips64 / mips64el - powerpc (ppc) / powerpc64 (ppc64) - sparc / sparc64 - s390 / s390x - sh / sh[1-5] / sh64 - x86_64 (amd64) Supported C Libraries: - glibc (gnu) - klibc [prob wont work] - musl - newlib [bare metal/no operating system] - uclibc [not all arches are ported] Special Targets: - avr http://www.nongnu.org/avr-libc/ - bfin http://blackfin.uclinux.org/ - h8300 http://h8300-hms.sourceforge.net/ - mingw32 http://www.mingw.org/ - mingw64 http://mingw-w64.sourceforge.net/ - msp430 http://mspgcc.sourceforge.net/ - nds32 http://github.com/nds32 - nios2 http://www.altera.com/products/ip/processors/nios2/ni2-index.html - xc16x http://www.infineon.com/ - ee / iop / dvp (ps2) [Playstation 2 targets] - ppu / spu (cell) [Cell/Playstation 3 targets] Softfloat toolchains: Include 'softfloat' in the 'vendor' field e.g. armeb-softfloat-linux-uclibc powerpc-booya_softfloat-linux-gnu
由上面的命令結果可以知道,基本上主流的 CPU 架構都支援,因此我們可以放心的學習使用 crossdev 建構不同平台的 toolchain.
假設我們今天要建構的 toolchain 是針對 ARMv7a
並且為 HardFloat
,執行於
Linux
環境的話,要怎樣作呢?在 Gentoo 下,使用以下命令 (其中 -S
代表選用
stable
版的套件)
Gentoo kernel # crossdev -S -t armv7a-hardfloat-linux-gnueabi
假設一切順利,你會看到 Gentoo 開始進行編譯,並把完整的 toolchain 編譯出來,不過通 常第一次執行的時候都會遇到如下錯誤 :(
* please convert /etc/portage/profile/package.use.mask to a directory * If you file a bug, please attach the following logfiles: * /var/log/portage/cross-armv7a-hardfloat-linux-gnueabi-info.log
這是因為 Gentoo 的 crossdev 必須在 /etc/portage/package.*
皆為 資料夾
的情況
才可以使用,因此你可以手動將那些檔案都變成資料夾,或是使用以下 腳本 幫你自動處理:
#!/bin/bash PROFILE_DIR="/etc/portage" if [ ! -e ${PROFILE_DIR} ]; then mkdir ${PROFILE_DIR}; fi for PACK_DIR in package.accept_keywords package.keywords package.use package.unmask package.mask; do CUR_DIR="${PROFILE_DIR}/${PACK_DIR}" if [ ! -e ${CUR_DIR} ]; then mkdir ${CUR_DIR} fi if [ -e ${CUR_DIR} -a ! -d ${CUR_DIR} ]; then mv ${CUR_DIR} ${CUR_DIR}.moving mkdir ${CUR_DIR} mv ${CUR_DIR}.moving ${CUR_DIR}/monolithic fi done echo "Completed!"
除此之外,由於 crossdev 會依據你建立的新的 toolchain,產生出相對應的 ebuild 檔案,因
此建議使用者擁有自己的 Local overlay。那我們要怎樣去建立 Local overlay 呢?首先
編輯 /etc/portage/make.conf
添加以下資訊
PORTDIR_OVERLAY="${PORTDIR_OVERLAY} /usr/local/portage"
接著建立 /usr/local/portage
資料夾
Gentoo kernel # mkdir -p /usr/local/portage
這樣當你使用 crossdev 建立新的 toolchain,就會在這個 Local overlay 看到相對應的 ebuild 被建立出來,如下
Gentoo kernel # tree -L 2 /usr/local/portage/ /usr/local/portage/ <b> ├── cross-armv7a-hardfloat-linux-gnueabi <b> │ ├── binutils -> /usr/portage/sys-devel/binutils <lb> │ ├── gcc -> /usr/portage/sys-devel/gcc <lb> │ ├── gdb -> /usr/portage/sys-devel/gdb <lb> │ ├── glibc -> /usr/portage/sys-libs/glibc <lb> │ └── linux-headers -> /usr/portage/sys-kernel/linux-headers <lb> ├── metadata <b> │ └── layout.conf └── profiles <b> └── categories 8 directories, 2 files
建立其他平台的 toolchain
在上面我們講解到了如何使用 crossdev 建立 ARMv7a HardFloat
的 Linux toolchain,
那如果我們的目標是裸版 (baremetal)呢?
針對裸版(baremetal)開發,我們的 toolchain 名稱就不會是 <arch>-linux-gnueabi
這
樣的組成,並且我們基本上只會使用 stage4
來進行編譯,在 crossdev 中,可以使用
-s
參數來指定要編譯的 stage,針對裸版 (baremetal) 的平台,我們基本上都會使用
--stage4
來建立 toolchain。
Stage Options: -s0, --stage0 Build just binutils -s1, --stage1 Also build a bare C compiler (no C library/ C++/shared GCC libs/C++ exceptions/etc...) -s2, --stage2 Also build kernel headers -s3, --stage3 Also build the C library -s4, --stage4 Also build a full compiler [default] (shared libs GCC/various lang frontends/etc...)
以下列出幾個不同平台的 toolchain 建立命令:
MSP430
Gentoo msp430 # crossdev -S -s4 -t msp430
ARM Cortex-M
Gentoo stm32 # crossdev -S -s4 -t arm-none-eabi
Ubuntu 的 arm-linux-gnueabihf
Gentoo stm32 # crossdev -S USE="-fortran -mudflap -nls -openmp multilib" EXTRA_ECONF="--with-cpu=cortex-a8 --with-float=hard" -t arm-linux-gnueabihf
測試我們建立的 toolchain
建立完 toolchain 後,我們可以用簡單的程式搭配 QEMU 來測試我們的 toolchain 是否能正常
工作,此處以 armv7a-hardfloat-linux-gnueabi-
作為範例,首先建立以下檔案並命名為 hello.c
#include <stdio.h> int main() { printf("Hello cross-compiling world!\n"); return 0; }
由於我們建立的 toolhcain 是針對 armv7a-hardfloat-linux-gnueabi
所建立,因此我們
會獲得 armv7a-hardfloat-linux-gnueabi-gcc
這個 gcc 命令,使用他來進行編譯
coldnew@Rosia ~ $ armv7a-hardfloat-linux-gnueabi-gcc hello.c -static -o hello
我們可以先使用 file
命令來檢查是否真的編譯為 ARMv7a 平台的程式
coldnew@Rosia ~ $ file hello hello: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, for GNU/Linux 2.6.32, not stripped
或是用 qemu-arm
直接執行這個 ELF 格式的程式
coldnew@Rosia ~ $ qemu-arm hello Hello cross-compiling world!