![]() |
|
嵌入式Linux編譯器GCC編譯流程 |
|
|
作(zuo)為自由軟件的(de)(de)旗艦(jian)項目,Richard Stallman在十多年(nian)前剛(gang)開始寫作(zuo)GCC的(de)(de)時候(hou),還只是僅(jin)僅(jin)把它(ta)當作(zuo)一個C程序語言的(de)(de)編譯器,GCC的(de)(de)意思也(ye)只是GNU C Compiler而已(yi)。 經過(guo)了這么多年的發展,嵌(qian)入式Linux編(bian)(bian)譯器(qi)GCC已經不(bu)(bu)僅僅能(neng)支持(chi)(chi)C語(yu)(yu)言(yan)(yan),它現在還支持(chi)(chi)Ada語(yu)(yu)言(yan)(yan)、C++語(yu)(yu)言(yan)(yan)、Java語(yu)(yu)言(yan)(yan)、Objective C語(yu)(yu)言(yan)(yan)、PASCAL語(yu)(yu)言(yan)(yan)、COBOL語(yu)(yu)言(yan)(yan),并支持(chi)(chi)函數式編(bian)(bian)程和邏輯編(bian)(bian)程的Mercury語(yu)(yu)言(yan)(yan)等(deng)。而GCC也不(bu)(bu)再單指GNU C語(yu)(yu)言(yan)(yan)編(bian)(bian)譯器(qi)的意思了,而是變成了GNU編(bian)(bian)譯器(qi)家族了。 GCC的編譯(yi)流程分為了(le)4個(ge)步驟,分別如下。 ·預處理(Pre-Processing)。 編譯器通過程(cheng)序的擴展(zhan)名(ming)可分(fen)辨(bian)編寫(xie)原始(shi)程(cheng)序碼所用(yong)的語(yu)言,由于不(bu)同(tong)的程(cheng)序所需要執行編譯的步驟是不(bu)同(tong)的,因此GCC根據不(bu)同(tong)的后綴名(ming)對它們進行分(fen)別處(chu)理(li),表1.1指出了不(bu)同(tong)后綴名(ming)的處(chu)理(li)方(fang)式。 GCC所支持后綴名解釋 GCC使用的基本語法為: 這(zhe)里(li)的(de)(de)option是(shi)GCC使用時(shi)的(de)(de)一些選(xuan)項,通過指定(ding)不(bu)同的(de)(de)選(xuan)項GCC可以實現其強(qiang)大的(de)(de)功能。這(zhe)里(li)的(de)(de)filename則是(shi)GCC要編譯(yi)的(de)(de)文件,GCC會根(gen)據用戶(hu)所(suo)指定(ding)的(de)(de)編譯(yi)選(xuan)項以及(ji)所(suo)識別的(de)(de)文件后(hou)綴名來(lai)對編譯(yi)文件進行相(xiang)應的(de)(de)處理。 本節從編(bian)譯流程的角(jiao)度(du)講解(jie)GCC的常見使(shi)用(yong)方法。 首先,這里有一段簡(jian)單的C語(yu)言程(cheng)序,該程(cheng)序由兩個文件(jian)組成,其中“hello.h”為(wei)頭文件(jian),在“hello.c”中包含了“hello.h”,其源文件(jian)如下所示。 /*hello.h*/ 1.預處理階段 GCC的選項“-E”可以使編譯器在預處理結束時就停止編譯,選項“-o”是指定GCC輸出的結果,其命令格式為如下所示。 表2.6指出后綴名為“.i”的文件是經過預處理的C原始程序。要注意,“hello.h”文件是不能進行編譯的,因此,使編譯器在預處理后停止的命令如下所示。 在此處,選項“-o”是指目標文件,由表2.6可知,“.i”文件為已經過預處理的C原始程序。以下列出了hello.i文件的部分內容。 由(you)此可見,GCC確實進行了(le)預處理,它把“hello.h”的(de)內(nei)容插入到hello.i文件中(zhong)了(le)。 2.編譯階段 編譯器在預處理結束之后,GCC首先要檢查代碼的規范性、是否有語法錯誤等,以確定代碼的實際要做的工作,在檢查無誤后,就開始把代碼翻譯成匯編語言,GCC的選項“-S”能使編譯器在進行完匯編之前就停止。由表1.1可知,“.s”是匯編語言原始程序,因此,此處的目標文件就可設為“.s”類型。 以(yi)下(xia)列出了hello.s的(de)內容,可見GCC已經將其轉(zhuan)化為匯編(bian)了,感興趣的(de)讀者(zhe)可以(yi)分析(xi)一下(xia)這(zhe)一行簡單的(de)C語言小程(cheng)序用匯編(bian)代碼是如(ru)何實現的(de)。 .file "hello.c" 可以看(kan)到(dao),這(zhe)一小段C語(yu)言(yan)的(de)程序(xu)在(zai)匯編(bian)中已經復(fu)雜很多了(le),這(zhe)也是(shi)C語(yu)言(yan)作為中級語(yu)言(yan)的(de)優勢所在(zai)。 3.匯編階段 匯編階段是把編譯階段生成的“.s”文件生成目標文件,讀者在此使用選項“-c”就可看到匯編代碼已轉化為“.o”的二進制目標代碼了,如下所示。 4.鏈接階段 在成功編譯(yi)之(zhi)后,就進入了(le)鏈接階段。在這里(li)涉(she)及一個重要的概念——函數(shu)庫(ku)。 在(zai)這個程(cheng)序(xu)中并沒(mei)有定義“printf”的(de)函數(shu)實現(xian),在(zai)預(yu)編譯中包(bao)含進的(de)“stdio.h”中也只有該函數(shu)的(de)聲明(ming),而沒(mei)有定義函數(shu)的(de)實現(xian),那么,是(shi)在(zai)哪里實現(xian)“printf”函數(shu)的(de)呢? 后的答案是:系(xi)統(tong)把這些函數(shu)實現都(dou)已經被(bei)放入名(ming)為libc.so.6的庫文件中(zhong)去(qu)了(le),在(zai)沒有特別(bie)指定時,GCC會到(dao)系(xi)統(tong)默認的搜(sou)索路(lu)徑“/usr/lib”下(xia)進行(xing)查(cha)找,也就(jiu)是鏈(lian)接(jie)到(dao)libc.so.6庫函數(shu)中(zhong)去(qu),這樣就(jiu)能(neng)實現函數(shu)“printf”了(le),而這也就(jiu)是鏈(lian)接(jie)的作用。 完成了鏈接之后,GCC就可以生成可執行文件,其命令如下所示。 運行該可執行文件,出現正確的結果。 熱點鏈接(jie):
1、WindowsAndroid:在PC上運行Android
|