在基於ARM的嵌入式系統開發中,常常用到交叉編譯的GCC工具鏈有兩種:arm-linux-*和
arm-elf-*,兩者區別主要在於使用不同的C庫檔案。arm-linux-*使用GNU的Glibc,而arm-elf-*一般使用
uClibc/uC-libc或者使用REDHAT專門為嵌入式系統的開發的C庫newlib.Glibc。uClibc/uC-libc以及
newlib都是C語言庫檔案,只是所應用的領域不同而已,Glibc是針對PC開發的,uClibc/uC-libc是與Glibc
API相容的小型化C語言庫,實現了Glibc部分功能。
關於uClibc/uC-libc的說明,詳見如下:
There are two libc libraries commonly used with uClinux. uC-libc and
uClibc. They are quite different despite their similar names. Here is a
quick overview of how they are different.
uC-libc is the
original library for uClinux. It was based on sources from the
Linux-8086 C library which was part of the ELKs project with m68000
support added by Jeff Dionne and Kenneth Albanowski. It is a fairly
complete libc implementation, however, some of the API's are a little
non-standard and quite a few common libc routines are not present.
Currently it has stable support for m68000, ColdFire and ARM (Non-MMU)
architectures. It was primary design goal is to be small and light
weight. It does try to conform to any standards, although its API tries
to be compatible with most libcs,
it is not always exactly the same.
The uClinux distribution provides an environment that can compile
using either uC-libc or uClibc depending on your needs. For m68000 and
Coldfire platforms it is generally better to chose uC-libc as it
supports shared libraries and is the most commonly used libc for these
CPUs. uClibc also works quite well with almost all platforms supported
by the distribution. Which libc you choose to use will be decided by
your requirements
譯文:
uClinux有兩個經常使用的libc庫:uC-libc和uClibc。雖
然兩者名字很相似,其實有差別,下面就簡單的介紹一下二者的不同之處。uC -libc是最早為uClinux開發的庫,是Jeff
Dionne和Kenneth Albanowski為在EKLs項目中支援m68000在Linux-8086
C庫源碼上移植的。uC-libc是一個完全的libc實現,但其中有一些api是非標準的,有些libc的標準也沒有實現。uC-libc穩定地支援
m68000,ColdFire和沒有MMU的ARM。其主要設計目標是“小”、"輕",並盡量與標準一致,雖然它的API和很多libc相容,但是似乎
並不像它期望的那樣和所有標準一致。
uClibc就是為瞭解決這個問題從uC-libc中發展出來的。它的所有API都是標準的(正確的
傳回型別,參數等等),它彌補了uC-libc中沒有實現的libc標準,現在已經被移植到多種架構中。一般來講,它盡量相容glibc以便使應用程式用
uClibc改寫變的容易。uClibc能夠在標準的 VM
linux和uClinux上面使用。為了應用程式的簡潔,它甚至可以在許多支援MMU的平台上被編譯成共用庫。Erik
Anderson在uClibc背後做了很多的工作。uClibc支援許多系列的處理器:m68000,Coldfire,ARM,MIPS,v850,
x86,i960,Sparc,SuperH,Alpha,PowerPC和Hitachi
8。不斷增加的平台支援顯示uClibc能夠很容易的適應新的架構。uClinux發行版提供了環境能夠讓你選擇使用uC-libc或是uClibc編
譯。對於m68000和Coldfire平台來說,選擇uC-libc還是稍微好一點,因為它支援共用庫,而共用庫是這些cpu經常使用的
libc.uClibc也幾乎和所有的平台都能很好的工作。選擇哪種libc取決於你的需求。
newlib
是一個用於嵌入式系統的開放原始碼的C語言程式庫,由libc和libm兩個庫組成,特點是輕量級,速度快,可移植到很多CPU結構上。newlib實現
了許多複雜的功能,包括字串支援,浮點運算,記憶體配置(如malloc)和I/O流函數(printf,fprinf()等等)。其中libc提供了c
語言庫的實現,而libm提供了浮點運算支援。
在為ARM交叉編譯gcc編譯器時,對gcc指定不同的配置選項時,使用的C語言庫就不
同,gcc編譯器預設使用Glibc,也可以使用 uClibc/uC-libc(基本相容Glibc
API),當使用--with-newlib時,gcc編譯器不使用Glibc。當沒有交叉編譯Glibc時,可以使用--with-newlib禁止連
接Glibc而編譯bootstrap
gcc編譯器。從gcc來源目錄下的config/arm中的t-linux和t-arm-elf中可以看出,不同的--target也影響gcc串連C語
言庫,t-linux(--target=arm-linux)預設使用Glibc,-arm-elf(--target=arm-elf)使用-
Dinhibit_libc禁止串連Glibc,這時我們就可以使用newlib等其他C語言庫編譯GCC工具鏈。
雖然GCC工具鏈配置
了不同的的C語言庫,但由於這些C語言庫都可以用來支援GCC,它們對核心資料的處理上不存在較大出入。因而arm-linux-* 和
arm-elf-*區別主要表現在C語言庫的實現上,例如不同系統調用,不同的函數集實現,不同的ABI/啟動代碼以及不同系統特性等微小的差別。
arm-linux-*和 arm-elf-*的使用沒有一個絕對的標準,排除不同庫實現的差異,gcc可以編譯任何系統。arm-linux-*和 arm-elf-*都可以用來編譯裸機程式和作業系統,只是在遵循下面的描述時系統程式顯得更加協調:
arm-linux-*針對運行linux的ARM機器,其依賴於指定的C語言庫Glibc,因為同樣使用Glibc的linux而使得arm-linux-*在運行linux的ARM機器上編譯顯得更加和諧。
arm-elf-*則是一個獨立的編譯體系,不依賴於指定的C語言庫Glibc,可以使用newlib等其他C語言庫,不要求作業系統支援,當其使用為
嵌入式系統而設計的一些輕巧的C語言庫時編譯裸機程式(沒有linux等大型作業系統的程式),如監控程式,bootloader等能使得系統程式更加小
巧快捷。
如果用一句話講清楚arm-linux-gcc和arm-elf-gcc的區別的話,如何來說呢?
arm-linux-gcc是針對arm + linux的開發環境的,kernel使用的是linux,不是uclinux,arm是有硬體MMU的。
而arm-elf-gcc是針對no MMU arm + uclinux的開發環境,kernel使用的是uclinux,硬體是廉價的無MMU的arm晶片。
arm-linux-gcc倒是有點類似X86 PC環境下的linux開發。
下面是一段英文的解釋:
xxx-elf is for standalone application. xxx-linux is for application running on
Linux. These two toolchains are almost same, except for different macros
defined when preprocessing and different libraries linked in when performing
linking.