顯示具有 cross compiler 標籤的文章。 顯示所有文章
顯示具有 cross compiler 標籤的文章。 顯示所有文章

2015年8月8日 星期六

Target Triple

剛好前鎮子有討論到 Target Triple 是啥鬼東西, 就順便整理一下,

在使用 Cross Compiler 的時候常常 gcc 前面會有一串名字,

例如 arm-none-linux-gnueabi-gcc 中的 arm-none-linux-gnueabi,

這東西其實真要說還真的沒啥正式的規則,

"通常"規則是 <target>[<endian>][-<vender>]-<os>[-<extra-info>]

然後這規則是自行歸納而來的並非啥正式規則

vendor 部份只是常見是可以塞 vendor 而已, 但沒有一定塞 vendor 的資訊
extra-info 部份大部份是在拿來描述用的 ABI 或著是 library 相關資訊

下面開使用一堆例子來用這規則來解讀
先以常見 x86 的平台為例子:
Fedora 22 上的 gcc (下 -v 可以看到)
Target: x86_64-redhat-linux
<target>-<vendor>-<os> 的形式

Ubuntu 14.04/i686 gcc
Target: i686-pc-linux-gnu
也是<target>-<vendor>-<os> 的形式

Android Toolchain:
Target: arm-linux-androideabi
<target>-<os>-<extra-info>
androideabi : 雖然 Android 本身是 Linux 但其 ABI 細節跟一般 linux 不太一樣

Linaro ELF toolchain:
Target: arm-none-eabi
<target>-<vender>-<extra-info>
vender = none
extra-info = eabi

Linaro Linux toolchain:
Target: arm-linux-gnueabihf
<target><endian>-<os>-<extra-info>
extra-info:
gnu: 沒啥特別意義
eabi: EABI
hf : Hard float, 預設有 FPU

Linaro big-endian Linux toolchain:
Target: armeb-linux-gnueabihf
<target><endian>-<vender>-<extra-info>
endian = be = big-endian

Buildroot 2015-02
Target: arm-buildroot-linux-uclibcgnueabi
<target>-<vender>-<os>-<extra-info>
extra-info:
uclibc 用 uclibc (通常預設是 glibc, uclibc 有些細節與 glibc 不同)
gnu : 無意義
eabi : 採用 EABI

NDS32 Toolchain:
Target: nds32le-elf
<target><endian>-<os>
Andes 家的,應該淺顯易懂不用解釋

由以上眾多 pattern 大概可以歸納出一些事情:
vender 那欄可以看上面的例子這部份完全可以亂填
os 那來可填可不填,不填"通常"代表 Non-OS (Bare-metal)

然後這鬼東西其實沒啥正式的規則
每個 target 可以按照自己開心的方式去處理
詳細部份可以參考 <gcc-src>/gcc/config.gcc [1]裡面有各種神秘規則

Reference

[1] https://github.com/gcc-mirror/gcc/blob/master/gcc/config.gcc

2012年1月21日 星期六

Clang + LLVM as cross compiler


Update Note:

  1. (2012/11/22) 目前 trunk 及 3.2 以後,將以 -target 取代那串語意不太清楚的 -ccc-host-triple, 所以如果 clang 跟你抱怨 clang: error: unsupported option '-ccc-host-triple' 的話請將文中指令的 -ccc-host-triple 替換成 -target

這篇文章主要講解怎麼把 Clang + LLVM 來當作一般的 Cross Compiler 來用, 也就是一般使用 arm-linux-gcc 一樣, 跟平常用 gcc 一樣就能動了

arm-linux-gcc hello.c -o hello

所以最終目標是想要

clang -arch arm hello.c -o hello

不過很殘念的是這只能在 Darwin 上可以這樣用...在 cfe-dev 上有人提過 [1]

而最近雖然有偉大的 ELLCC 可以用, 但其使用的 C Library 看起來還不太齊全(至少不夠編出 SPEC2000, 來自 NetBSD C Library), 而且編譯 SPEC2000 的 perlbmk 也會鬼打牆似的 symbol redefine ...

所以在 ELLCC 成熟前先將就點退而其之用 clang 撐著用

用 Clang + LLVM 當 cross compiler 注意 LLVM 當初編的時候 Target 要開, 免得耍蠢

在這邊先假設已經有 Clang + LLVM 的執行檔下開始作說明

我們的暫定目標是將 Clnag + LLVM 弄成可以編出 arm-linux 上的程式

首先先弄一套 arm linux toolchain 懶得自己編就去弄一套 Code Sourcery 的以下是其中一個版本的 連結 (選IA32 GNU/Linux TAR)

或著是你可以到此 頁面 下載最新版

然後解壓縮放在你家, 接著確認他會不會動

# ~/arm-2011.09/bin/arm-none-linux-gnueabi-gcc -v

Using built-in specs.
COLLECT_GCC=arm-2011.09/bin/arm-none-linux-gnueabi-gcc
COLLECT_LTO_WRAPPER=/home/kito/arm-2011.09/bin/../libexec/gcc/arm-none-linux-gnueabi/4.6.1/lto-wrapper
Target: arm-none-linux-gnueabi
...
確認會動後下一步終於要啟動 clang 了
首先先將你的 arm-linux-gcc 的資料夾弄給 clang 知道
不用加 bin/, clang 會掃描該自料夾
clang -gcc-toolchain /home/kito/arm-2011.09/
主要原因是 clang 會去找 gcc 來用, 以此辨別 ld 跟 as 位置

接著
clang -gcc-toolchain /home/kito/arm-2011.09/  -ccc-host-triple arm-none-linux-gnueabi hello.c
看起來是這樣應該就要可以動了
但實際跑起來會跟你抱怨找不到 Library, 以及很嚴重的是 include 檔是抓 x86 的

/home/kito/arm-2011.09//lib/gcc/arm-none-linux-gnueabi/4.6.1/../../../../arm-none-linux-gnueabi/bin/ld: warning: library search path "/lib/../lib64" is unsafe for cross-compilation /home/kito/arm-2011.09//lib/gcc/arm-none-linux-gnueabi/4.6.1/../../../../arm-none-linux-gnueabi/bin/ld: warning: library search path "/usr/lib/../lib64" is unsafe for cross-compilation /home/kito/arm-2011.09//lib/gcc/arm-none-linux-gnueabi/4.6.1/../../../../arm-none-linux-gnueabi/bin/ld: warning: library search path "/lib" is unsafe for cross-compilation /home/kito/arm-2011.09//lib/gcc/arm-none-linux-gnueabi/4.6.1/../../../../arm-none-linux-gnueabi/bin/ld: warning: library search path "/usr/lib" is unsafe for cross-compilation /usr/lib/../lib64/crt1.o: file not recognized: File format not recognized clang-3: error: linker command failed with exit code 1 (use -v to see invocation)

所以下一步驟是加入搜索路徑

clang -ccc-host-triple arm-none-linux-gnueabi --sysroot=/home/kito/arm-2011.09/arm-none-linux-gnueabi/libc/ hello.c

然後~噁他在動~!!!
但相信只要是人都會覺得那串太長
所以把下面那串弄到 .bashrc 裡

alias arm-clang='/home/kito/llvm/llvm/bin/clang -gcc-toolchain /home/kito/arm-2011.09/ -ccc-host-triple arm-none-linux-gnueabi --sysroot=/home/kito/arm-2011.09/arm-none-linux-gnueabi/libc/'

從今以後也可以使用簡單的方式來編譯了

arm-clang hello.c -o hello

若要驗證可使用 qemu-arm 來驗證, 不過記得要加 -static 參數

最後要注意的是 sysroot 裡面的路徑 /home/kito/ 不可縮減為 ~/ 會因此找不到路徑呦



備註:
  1. clang 可使用 -march 來指定最佳化的ISA,如-march=armv4, -march=armv7
  2. clang 跟 gcc 在一些細節支援上有些不同, 必須留意(例如 clang 不支援 register storage class global variable )
  3. 上敘的使用方法還是會相依到 libgcc, 如果是要研究用途的請留意, 有個東西叫 compiler-rt 是 libgcc 的替代品, 但目前還不知道怎麼整進去
  4. 上敘的方法有拿去編譯 uClibc 跟 SPEC2000 試過了

[1] http://lists.cs.uiuc.edu/pipermail/cfe-dev/2010-July/009878.html