林炎,張友益
(1.江蘇科技大學 電子信息學院,鎮(zhèn)江212003;2.中國船舶重工集團公司 第七二三研究所)
隨著計算機技術、網絡技術和微電子技術的深入發(fā)展,嵌入式系統(tǒng)的應用無處不在。交叉編譯是伴隨嵌入式系統(tǒng)的發(fā)展而來的[1]。傳統(tǒng)的程序編譯方式,生成的程序直接在本地運行,這種編譯方式稱作本地編譯;嵌入式系統(tǒng)多采用交叉編譯的方式,在本機編譯好的程序是不能在本機運行的,需要通過特定的手段(例如燒寫、下載等)安裝到目標系統(tǒng)上執(zhí)行。交叉編譯的實現克服了嵌入式系統(tǒng)目標平臺存儲空間和運算能力有限的缺點[2],完善的工具鏈可以保證項目開發(fā)的進度和質量[3],是嵌入式開發(fā)的第一步,也是關鍵的一步[4]。
交叉編譯環(huán)境包括兩個部分,其中,本機Linux環(huán)境是重要的基礎?;诒緳CLinux環(huán)境,構建交叉編譯工具鏈是關鍵。
本機的Linux環(huán)境可以選擇安裝Linux操作系統(tǒng),或者在Windows下安裝虛擬Linux環(huán)境軟件[5]。Linux環(huán)境中有很多優(yōu)秀的開源開發(fā)工具,而Windows是目前PC機上最普及的操作系統(tǒng)。為了兼顧Linux和Windows,選擇在Windows下安裝虛擬Linux環(huán)境。Windows下安裝虛擬Linux環(huán)境主要有以下3種方式:
①虛擬機,如Vmware、VirtualBox等。虛擬機虛擬出一臺真實的計算機出來,只需要在這臺虛擬計算機上安裝Linux,其效果和真實Linux系統(tǒng)完全一樣。但這樣所需占用的系統(tǒng)資源相當多,速度受硬件配置的限制很大[6]。
②CoLinux及其衍生品,如AndLinux。CoLinux 創(chuàng)建的是一個真正的Linux操作系統(tǒng)[7],其原理是將一個發(fā)行版Linux“改造”為一個Windows平臺下的應用程序,并以原生方式運行Linux的軟件。這是一個很有潛力的解決方案,但目前存在兩個很明顯的軟肋:一是被改造好的發(fā)行版數量非常有限,版本也非常陳舊;二是僅僅支持32位機的安裝。
③Cygwin。Cygwin是由RedHat公司負責維護的,經多年來不斷的發(fā)展,對于Linux的虛擬日臻成熟。Cygwin的設計思想十分巧妙,它在Windows上設計了一個Linux系統(tǒng)調用中間層,模擬Linux的系統(tǒng)調用,只需要把Linux下的工具在Windows系統(tǒng)重新編譯,做一些較小的修改即可移植到Windows 系統(tǒng)。Cygwin 幾乎移植了Linux系統(tǒng)常用的所有開發(fā)工具[2],用戶可以根據自身的需要裝卸,十分靈活。Cygwin作為開源軟件,支持32/64位機的安裝,占用系統(tǒng)資源少,運行速度快,指令與Linux基本一致,更可以方便地與Windows共享文件(夾)。
①從http://cygwin.com 下載最新的Cygwin。
②安裝Cygwin。首次安裝通常選擇直接從Internet下載(Install from Internet)安裝的模式,并選擇一個目錄作為安裝包的存放路徑(Local Package Directory)。下載好的安裝包將被保留在這個目錄中,以便再次安裝時直接由本地安裝(Install from Local Directory)。更新時,安裝程序將只下載比這個目錄中更新的安裝包。
③下載鏡像的選擇。Cygwin提供了大量的鏡像下載站點,用戶可以選擇一個合適的站點下載安裝包。再次安裝時,還應選擇同一個站點。
④安裝包的選擇是Cygwin安裝與配置過程中最重要的一步。選擇全部安裝包下載,需要很長的時間,且安裝大量無用的安裝包之后,還會大大地影響到Cygwin運行的速度。對于嵌入式開發(fā)而言,建議將Archive、Base、Devel、Doc、Editors、Interpreters、Libs、Net、Shells、System、Text、Utils、Web下的安裝包全部(all)安裝,其他安裝包缺?。╠efault)安裝。
安裝成功后,便可進入到Cygwin環(huán)境,命令行提示符為“$”。Linux的文件系統(tǒng)都是從“/”開始的,Cygwin的“/”就是在Windows中的安裝路徑(如X:\cygwin)。
對于Cygwin而言,交叉工具鏈通常有3個來源——已經制作好的交叉編譯鏈、分步手工編譯交叉工具鏈以及使用腳本自動生成的交叉工具鏈。
如GNU ARM toolchain[9],選擇Cygwin版本下載、安裝好后,在Cygwin中就可直接使用,十分方便,但只適用于無MMU 的嵌入式Linux(如ucLinux);又如廠商提供的交叉工具鏈,都是廠商測試通過的,可靠性很高,而且與開發(fā)板能夠很好地吻合,但是由于時間滯后的原因,往往都不是最新的版本,當系統(tǒng)內核升級后,會出現兼容性問題[10]。最重要的是,Cygwin 并不支持以原生方式運行Linux程序,如果廠商沒有提供Cygwin中可以使用的交叉工具鏈,這種方法就是不可行的。總而言之,使用已經做好的交叉工具鏈有很大的局限性。
分步手工編譯交叉工具鏈即分別編譯和安裝交叉工具鏈所需要的庫和源代碼。執(zhí)行上比較困難,需要比較清楚地了解每個工具鏈軟件的相互匹配情況,而且也可能會受到不同的發(fā)行版之間差別的影響,比較容易出錯或者編譯不通過[11]。
自動生成的交叉工具鏈最著名的當屬Crosstool。但用Crosstool編譯的交叉工具鏈,GCC版本只能到4.1.1,無法編譯版本高于2.6.29的Linux內核。Crosstool-NG(Crosstool-Next Generation)是Crosstool 的替代者。Crosstool-NG一直保持著更新,隨著開源社區(qū)更新和改進GCC、Glibc以及相關的工具,與編譯工具鏈相關的代碼也會不斷發(fā)生演化,這使得它能很好地完成維護任務。[12]
Crosstool-NG 會自動完成Linux環(huán)境下頭文件、庫文件、內核版本和交叉編譯工具鏈的匹配,方法簡單易行,也不容易出錯[11]。下文就詳細介紹了如何在“Windows 7 64bit+Cygwin 1.7.16-1”平臺下,利用Crosstool-NG 1.16.0,針對32 位ARM 核S3C6410 微處理器,搭建Linux交叉編譯環(huán)境。
①將Windows系統(tǒng)設置區(qū)分大小寫模式。Unix和類Unix系統(tǒng)(如Linux)都是區(qū)分大小寫的。Cygwin模擬Unix環(huán)境也要求區(qū)分大小寫,但Windows系統(tǒng)本身對大小寫并不加以區(qū)分。解決的辦法是將注冊表中HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Kernel項中“obcaseinsensitive”值置為“0”,重啟計算機后,Cygwin下就可以區(qū)分大小寫了。
②從http://crosstool-ng.org下載最新的Crosstool-NG,將壓縮包復制到Cygwin 的/home/ng/下,進入目錄,解壓壓縮包$tar-jxvf crosstool-ng-1.16.0.tar.bz2,再進入解壓目錄$cd crosstool-ng-1.16.0。如果有補丁文件,也下載到此目錄下,為Crosstool-NG 打補丁($patch-p1 <<補丁文件>)。
③針對Cygwin,對Crosstool-NG 作如下幾處修改。(a)修改kconfig/Makefile。在“$(conf_OBJ)$(conf_DEP):CFLAGS+= $(INTL_CFLAGS)”后加上“conf:LDFLAGS+=-lintl”一行,將“mconf:LDFLAGS+= $(NCURSES_LDFLAGS)”修改為“mconf:LDFLAGS+= -lintl $(NCURSES_LDFLAGS)”,將“nconf:LDFLAGS+=-lmenu-lpanel-lncurses”修改為“nconf:LDFLAGS+=-lintl-lmenu-lpanel-lncurses”。(b)修改kconfig/nconf.c。將“ESCDELAY=1;”修改為“set_escdelay(1);”。
④配置Crosstool-NG($./configure--prefix=/opt/ng/install),經過編譯($make)后,安裝Crosstool-NG($make install)。
⑤創(chuàng)建交叉工具鏈的構造目錄($mkdir-p/opt/ng/build)和源碼包目錄($mkdir-p/opt/ng/src),并根據目標系統(tǒng)CPU 的情況,從配置模板目錄中拷貝相應的參考config文件到構造目錄($cp/opt/ng/install/lib/ct-ng.1.16. 0/samples/arm-unknown-linux-gnueabi/*/opt/ng/build),進入構造目錄($cd/opt/ng/build),將config文件改更名為.config($mv crosstool.config.config)。為方便調用 ct-ng,修改環(huán)境變量 ($export PATH=${PATH}:/opt/ng/install/bin)。
⑥進入配置交叉工具鏈界面($ct-ng menuconfig)。
(a)首先,設置保存編譯的中間步驟,勾選上Debug Crosstool-NG,以及隨之產生的Save intermediate steps項。編譯工具鏈出錯是很難避免的,記錄下編譯的每一步狀態(tài),在出現錯誤并糾正錯誤之后,Crosstool NG 就可以從出錯的那一步開始繼續(xù)編譯。然后,設置編譯工具鏈所需源碼包的目錄(Local tarballs directory)為/opt/ng/src以及交叉編譯器的安裝目錄(Prefix directory)為/usr/crosstool-ng。最后,增加編譯時的并行進程數(Number of parallel jobs),以提高運行效率。這個數值一般應為CPU核數的兩倍,如雙核CPU 就應填4。
(b)對于ARM 核S3C6410而言,Target Architecture和Default instruction set mode缺省的配置已經是arm,不用修改。指令集的架構(Architecture level)應設置為armv6。處理器的類型(Emit assembly for CPU)應設為arm1176jzf-s。浮點選項(Floating point)應選硬件VFP(hardware FPU)。
(c)Toolchain options。在Tuple's vendor string前的括號中可以輸入個性化的前綴名,如輸入lynn,就將產生名為arm-lynn-linux-gnueabi-的交叉工具鏈。留空的話,最后生成的工具鏈的名字是arm-unknown-linux-gnueabi-。
(d)在Operating System 中選擇合適的嵌入式Linux內核版本號。
(e)在Binary Utilities中設置Binutils庫的版本號。Binutils是一個二進制工具集合,包含了匯編器、反匯編器、連接器、ELF可執(zhí)行文件分析器等重要工具[14]。
(f)在C Compiler中設置交叉編譯器GCC的版本號和所要支持的語言。GCC 是一組編譯工具的總稱,包括C/C++語言編譯器、源代碼處理程序和各種庫文件[15]。建議關閉Fortran和Java語言的支持,因為這些語言通常無法針對目標機通過編譯。[12]
(g)在C--library中設置交叉編譯器所要支持的C庫及其版本號(注意選上“Forced unwind support”)。Glibc是Linux系統(tǒng)中最底層的應用程序開發(fā)接口(API),包含了各種函數庫[6],所有動態(tài)鏈接的程序都要用到它。這里需要注意的是,Glibc和內核源代碼的版本必須與目標機上實際使用的版本保持一致[15]。
(h)在Debug facilitites中配置交叉編譯器的調試工具。其中,ltrace不支持Linux的虛擬環(huán)境,不要選擇;而duma需要進行一定的修改之后才能被編譯(將duma源碼包解壓縮,打開GNU makefile文件,在ECHOLF=echo后添加OS=cygwin,再將duma重新打包);GDB 最為常用,可以調試C和C++語言程序[1]。
(i)在Companion library中設置GMP、MPFR、PPL、CLooG/ppl、MPC的版本號,它們是除C 庫以外,交叉編譯工具額外需要的庫。
(j)保存配置(Save an Alternate Configuration File),退出配置界面(Exit)。
Crosstool-NG 會自動下載、解壓、配置、編譯、鏈接所需的源碼包。不過,為了加快制作工具鏈的進度,可以通過查看經過完成配置之后的config文件,預先下載好其中提及的源碼包(壓縮包格式不限),并將它們全部放入源碼包目錄內,便可交由腳本工具開始制作交叉編譯鏈($ctng build)。
經過若干小時的編譯,編譯好的工具鏈將保存在交叉編譯器的安裝目錄中。我們可以看到,生成的所有工具擴展名都是“.exe”,也就是說,這些工具都是在Windows系統(tǒng)下運行的執(zhí)行程序。
添加交叉工具鏈到環(huán)境變量($vi/etc/profile,也可在Windows中用文本編輯器修改X:\cygwin\etc\profile),在文件的末尾添加交叉工具鏈的路徑(PATH=$PATH:/usr/crosstool-ng/arm-lynn-linux-gnueabi/buildtools/bin),立即更新環(huán)境變量($source/etc/profile),工具鏈就可以直接使用了。如輸入指令“$arm-lynn-linuxgnueabi-gcc-v/--version”,就可查看工具鏈的版本。
為方便使用,可以為交叉工具鏈建立“快捷方式”。進入交叉工具鏈的目錄($cd/usr/crosstool-ng/arm-lynnlinux-gnueabi/buildtools/bin),建立符號鏈接(如$ln-s arm-lynn-linux-gnueabi-gcc arm-linux-gcc)。注意鏈接名不要與本地編譯器同名。
交叉編譯環(huán)境搭建好之后,必須通過編譯文件來驗證其是否能夠正常工作。寫一個最簡單hello.c源文件:
在交叉編譯環(huán)境中,對以上程序進行交叉編譯($arm-linux-gcc hello.c-o hello),生成名為hello 的文件。查看文件信息($file hello),看到類似“hello:ELF 32-bit LSB executable,ARM,version1(SYSV),dynamically linked(uses shared libs),for GUN/Linux 2.6.39,not stripped”的信息,即表明成功地編譯了一個可以在ARM體系結構下運行的可執(zhí)行文件,交叉編譯環(huán)境已經被成功地搭建。
本文介紹了在Windows平臺下,基于Cygwin 虛擬Linux系統(tǒng),利用Crosstool-NG 建立ARM-Linux交叉編譯環(huán)境的方法。驗證結果表明,本方法適用于ARMLinux的開發(fā)。對于Crosstool-NG 所支持的基于其他嵌入式CPU 的目標系統(tǒng),如MIPS、PowerPC 等,在Windows下構建Linux交叉編譯環(huán)境,完全可以參照ARMLinux交叉編譯環(huán)境的構建方法進行。
[1]雷鴻.基于虛擬機架構下嵌入式開發(fā)環(huán)境搭建的研究與實現[J].信息通信,2011(4):11-13.
[2]弓雷.ARM 嵌入式Linux系統(tǒng)開發(fā)詳解[M].北京:清華大學出版社,2010.
[3]李新峰,何廣生.基于ARM9的嵌入式Linux開發(fā)技術[M].北京:電子工業(yè)出版社,2008.
[4]華清遠見.嵌入式Linux C語言應用程序設計[M].北京:人民郵電出版社,2007.
[5]熊光澤,羅蕾.嵌入式軟件技術的發(fā)展現狀與發(fā)展動向[J].計算機應用,2000,20(7):23-26.
[6]劉永林,梁瑩,王詩琴,等.基于Linux的嵌入式交叉編譯環(huán)境的建立及實現[J].電腦開發(fā)與應用,2011,24(7):68-70.
[7]趙慶明,羅蕾,周建斌,等.CoLinux在構建嵌入式開發(fā)環(huán)境中的應用[J].微計算機信息,2009(23):15-17.
[8]Cygwin.Cygwin User's Guide[R/OL].[2012-11-10].http://cygwin.com/cygwin-ug-net/cygwin-ug-net.html.
[9]趙峰.ARM 交叉編譯和調試[R/OL].[2012-11-10].http://www.eefocus.com/article/07-11/28362s.html.
[10]張歡慶,高麗,宋承祥.基于ARM 的嵌入式Linux交叉編譯環(huán)境的研究與實現[J].計算機與數字工程,2012,40(2):151-153.
[11]劉二鋼.利用Crosstool-NG 構建交叉編譯工具鏈[J].電腦知識與技術,2011,7(7):4553-4554,4567.
[12]Gene Sally.Pro linux embedded systems[M].California:Apress,2009.
[13]Yann Morin.Download and usage[R/OL].[2012-11-10].http://crosstool-ng.org.
[14]張瑞,于德海,馬明龍.基于ARM 的嵌入式Linux的交叉編譯環(huán)境的建立[J].科技信息,2009(25):508-509.
[15]李勝琴,張國榮,許巖.基于ARM 的交叉編譯工具的制作[J].太原師范學院學報:自然科學版,2010,9(2):36-38.