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