原創博文,轉載請注明出處。
GCC的編譯過程分為預處理、生成匯編代碼、生成目標代碼和鏈接成可執行文件等4個步驟。
使用vim編寫C 文件 : [lining@localhost program]$ vim hello.c 這樣就會在program文件夾生成hello.c文件
編譯C代碼:使用如下命令“gcc 代碼文件名”? 如: [lining@localhost program]$ gcc hello.c 這樣就會生成二進制可執行文件名稱位a.out。
????????? 如果需要指定輸出的文件名稱,使用 “gcc -o 代碼文件名” 如:[lining@localhost program]$ gcc -o hello hello.c 這樣就會生存名稱為hello的可執行文件。
???????? [lining@localhost program]$ gcc -v -o hello hello.c 使用參數v可以顯示GCC的工作整個過程。
編譯C ++代碼:與編譯C 代碼類似,只不過要把gcc換成g++。
使用GCC控制編譯過程:
1、預處理
??????????? 該步驟完成宏和include展開工作。在GCC 中使用參數E可控制GCC完成預處理。
?????????? [lining@localhost program]$ gcc -E -o hello.pre.c hello.c 可通過查看hello.pre.c文件內容驗證
?????? 2、生成匯編代碼
?????????? 編譯器將預處理生成的代碼進行處理,并根據編譯參數進行優化,最后生成匯編代碼。使用參數S。
????????? [lining@localhost program]$ gcc -S hello.c 將生成名為hello.s的匯編代碼。
3、生成目標代碼
?????????? 目標代碼生成階段是把中間代碼變換成特定機器上的絕對指令代碼、可重定位的指令代碼或匯編指令代碼。GCC中使用參數c完成預編譯、生成匯編代碼和生成目標代碼。
?????????? [lining@localhost program]$ gcc -c hello.c 將生成名為hello.o的目標代碼。
4、鏈接生成最終可執行代碼
??????????? 這一步相當與前面的程序編譯。
補充知識 :gcc -shared -fPIC -o 1.so 1.c
我們總是用fPIC來生成so,也從來不用fPIC來生成a. fPIC與動態鏈接可以說基本沒有關系,libc.so一樣可以不用fPIC編譯,只是這樣的so必須要在加載到用戶程序的地址空間時重定向所有表目.
GNU Make項目管理
??????? Make按照一定的規則對項目的源文件進行編譯,并生成可執行的二進制文件。在使用gcc編譯項目文件時,由于項目源文件代碼很多,每次修改任何一個源代碼文件都要重新編譯和鏈接。
?Make通過讀入配置好的文本文件,并根據文本文件中預先定義的規則和步驟,完成代碼的編譯和鏈接工作,最終生成所需要的項目文件。這個文本文件在缺省情況下文件名為makefile或Makefile。Make程序的命令形式是 “make[選項]、[目標]...”,可通過make -h 查看所支持選項。
??????? Make 在進行項目編譯時會讀makefile文件,比較該目標所依賴的源文件額日期和時間,以確定要編譯的代碼和相關的編譯規則。當用戶輸入make命令后,Make將首先搜索該目錄下是否存在makefile。如果沒找到,則搜索名為makefile的文件,最后查找名為Makefile的文件。用戶可通過 -f參數來指定makefile配置文件。
makefile的語法
makefile文件由一組依賴關系和規則構成。每個依賴關系由一個目標(即將要創建的文件)和一組該目標所依賴的源文件組成。makefile的內容包含5個部分:顯式規則,隱式規則,變量定義,指令和注釋。
?????? 這里主要介紹變量和指令這兩個主要的部分。
?????? 變量:區分大小寫,與C/C++不同,定義變量不需要先聲明。在定義變量后,如果要引用該變量,可以使用$(變量名)的形式訪問該變量。
?????????? ? ? ?? 對上面的hello.c 編寫帶有變量定義的makefile ???
CC =
gcc
hello : hello.c
$(CC)
-o hello hello.c ? ?//這兒需要注意,第二行的開頭是tab字符,如果使用空格會在make命令下出現提示
???????????????? 完成編輯后,將其保存為makefile文件。在shell命令下輸入make命令,編輯文件。
???????????????? makefile中有一些預先設定的變量:
?????????????????? $@?? 表示當前規則中的目標文件名
????????????????????????? $????? 新修改過的依賴文件列表
????????????????????????? $*????? 不包含擴展名的目標文件名
????????????????????????? $<????? 當前規則中的第一個依賴文件名
????????????????????????? $%???? 當目標文件為庫文件時,該變量為庫文件名;如果不是庫文件,該變量為空值
????????????????????????? $^????? 當前規則中的所有文件列表
????????????????????????? AR???? 歸檔程序名稱,默認為AR
????????????????????????? ARFLAGS????? 歸檔程序選項
???????????????????????? CC????? C編譯器命令名,默認為CC
???????????????????????? CFLAGS???? C編譯器編譯參數
基于依賴關系的指定區:
?????????????? 依賴關系定義了最終應用程序里的每個文件與源文件之間的關系。規則的寫法如下
?????????????????????? 目標(可能存在多個目標)... :空格或tab鍵 依賴條件(可能存在多個依賴條件,以空格或tab隔開)...
舉例如下:
myapp: main.o
2
.o
3
.o
main.o: main.c a.h
2
.o:
2
.c a.h b.h
3
.o:
3
.c b.h c.h
它表示目標myapp依賴于main.o,2.o和3.o, 而main.o依賴于 main.c和a.h,等等。如果你沒有指定目標的名字作為make命令的一個參數,make命令將第一個目標定義為all。
myapp: main.o
2
.o
3
.o
gcc
-o myapp main.o
2
.o
3
.o
main.o: main.c a.h
gcc
-
c main.c
2
.o:
2
.c a.h b.h
gcc
-c
2
.c
3
.o:
3
.c b.h c.h
gcc
-c
3
.c
當我們執行make -f makefile1(我們把創建的第一個makefile自定義命名),首先會檢查其他的依賴關系,最終確定需要有一個文件main.c。在這里我們令頭文件都是空文件,我們可以用touch命令來創建它們:
[lining@localhost program]$ touch a.h
[lining@localhost program]$ touch b.h
[lining@localhost program]$ touch c.h
1
#include <stdlib.h>
2
#include <stdio.h>
3
#include
"
a.h
"
4
extern
void
function_two();
5
extern
void
function_three();
6
void
main()
7
{
8
function_two();
9
function_three();
10
printf(
"
%s\n
"
,
"
This is a test
"
);
11
}
2.c 和3.c
/*
2.c
*/
1
#include
"
a.h
"
2
#include
"
b.h
"
3
void
function_two(){
4
}
/*
3.c
*/
1
#include
"
b.h
"
2
#include
"
c.h
"
3
void
function_three(){
4
}
然后執行make命令:make -f makefile1生成目標文件myapp,再執行如下命令:
[lining@localhost program]$ ./myapp
This is a test
如果我們使用變量將使得我們在以后的維護過程中更加方面,我們把上面的makefile文件改造
CC=
gcc
CFLAGS1
=-
o
CFLAGS2
=-
c
myapp: main.o
2
.o
3
.o
$(CC) $(CFLAGS1) $@ main.o
2
.o
3
.o
main.o: main.c a.h
$(CC) $(CFLAGS2) main.c
2
.o:
2
.c a.h b.h
$(CC) $(CFLAGS2)
2
.c
3
.o:
3
.c b.h c.h
$(CC) $(CFLAGS2)
3
.c
clean:
rm main.o
rm
2
.o
rm
3
.o
使用 clean 可將中間生成的文件做必要的清理,這樣目標就沒有依賴關系了。在正常情況下,如果沒有告訴Make執行clean命令(make -f makefile1 clean),clean將永遠不被執行。
Make在makefile中沒有指明具體處理規則時會采用慣例來處理。例如,將后綴.c的文件編譯為.o文件,也就說說我們不必寫出將后綴.c的文件編譯為.o文件的規則,Make命令就自動識別并執行。常見的隱含規則如下:
?????? C 程序編譯: .o文件自動由同名的.c文件生成,編譯命令為: $(CC) -c $(CPPFLAGS) $(CFLAGS)
?????? C++程序編譯: .o文件自動由同名的.c文件或.cc文件生成,編譯命令為:$(CXX) -c $(CPPFLAGS) $(CFLAGS)
Pascal程序編譯: .o文件自動由同名的.p生成,編譯命令為:$(PC) -c $(PFLAGS)
makefile的模式規則:
?????? Make支持編寫模式規則來定義用戶自己的隱含規則。相比于一般的規則,模式規則在形式上只是含有“%”的通配符(其功能類似于shell中的“*”)。如果確定了依賴關系中的“%”模式,Make就會按要求去匹配當前目錄下的所有文件名,一旦找到符合規則的文件,Make就會執行該規則下的命令。如
%.o : %
.c
$(CC)
-c $(CFLAGS) $(CPPFLAGS) $< -o $@
該模式規則表示當前目錄下的所有以.c結尾的文件編譯成以.o結尾的目標文件。宏$<將被擴展為起始文件的名字。而$@將被替換成生成的目標文件。
?關于調試的知識將在以后的章節中介紹。
?
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

