共計 3725 個字符,預(yù)計需要花費 10 分鐘才能閱讀完成。
今天丸趣 TV 小編給大家分享一下 linux 里的 gcc 怎么使用的相關(guān)知識點,內(nèi)容詳細(xì),邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
在 linux 中,gcc 全稱“GNU Compiler Collection”,中文意思為“GNU 編譯器套件”,是由 GNU 開發(fā)的編程語言編譯器,是一個能夠編譯多種語言的編譯器。gcc 套件包括 C、C++、Objective-C、Fortran、Java、Ada 和 Go 語言前端,也包括了這些語言的庫。
1、什么是 gcc
GCC(GNU Compiler Collection,GNU 編譯器套件)是由 GNU 開發(fā)的編程語言編譯器,它是一個能夠編譯多種語言的編譯器。GNU 編譯器套件包括 C、C++、Objective-C、Fortran、Java、Ada 和 Go 語言前端,也包括了這些語言的庫(如 libstdc++,libgcj 等。)
最開始 gcc 是作為 C 語言的編譯器(GNU C Compiler),現(xiàn)在除了 c 語言,還支持 C ++、java、Pascal 等語言。gcc 支持多種硬件平臺。
2、gcc 的特點
gcc 是一個可移植的編譯器,支持多種硬件平臺。例如 ARM、X86 等等。
gcc 不僅是個本地編譯器,它還能跨平臺交叉編譯。所謂的本地編譯器,是指編譯出來的程序只能夠在本地環(huán)境進(jìn)行運行。而 gcc 編譯出來的程序能夠在其他平臺進(jìn)行運行。例如嵌入式程序可在 x86 上編譯,然后在 arm 上運行。
gcc 有多種語言前端,用于解析不同的語言。
gcc 是按模塊化設(shè)計的,可以加入新語言和新 CPU 架構(gòu)的支持。
gcc 是自由軟件。任何人都可以使用或更改這個軟件。
3、gcc 編譯程序的過程
gcc 編譯程序主要經(jīng)過四個過程:
預(yù)處理(Pre-Processing)
編譯(Compiling)
匯編(Assembling)
鏈接(Linking)
預(yù)處理實際上是將頭文件、宏進(jìn)行展開。編譯階段,gcc 調(diào)用不同語言的編譯器,例如 c 語言調(diào)用編譯器 ccl。gcc 實際上是個工具鏈,在編譯程序的過程中調(diào)用不同的工具。匯編階段,gcc 調(diào)用匯編器進(jìn)行匯編。鏈接過程會將程序所需要的目標(biāo)文件進(jìn)行鏈接成可執(zhí)行文件。匯編器生成的是可重定位的目標(biāo)文件,學(xué)過操作系統(tǒng),我們知道,在源程序中地址是從 0 開始的,這是一個相對地址,而程序真正在內(nèi)存中運行時的地址肯定不是從 0 開始的,而且在編寫源代碼的時候也不能知道程序的絕對地址,所以重定位能夠?qū)⒃创a的代碼、變量等定位為內(nèi)存具體地址。
下面以一張圖來表示這個過程,注意過程中文件的后綴變化,編譯選項和這些后綴有關(guān)。
這是 GCC 編譯的四個步驟。
4、gcc 常用選項
來看一下 gcc 常用選項
現(xiàn)在我們有源文件 hello.c,下面是一些 gcc 的使用示例:
gcc -E hello.c -o hello.i 對 hello.c 文件進(jìn)行預(yù)處理,生成了 hello.i 文件
gcc -S hello.i -o hello.s 對預(yù)處理文件進(jìn)行編譯,生成了匯編文件
gcc -c hello.s -o hello.o 對匯編文件進(jìn)行編譯,生成了目標(biāo)文件
gcc hello.o -o hello 對目標(biāo)文件進(jìn)行鏈接,生成可執(zhí)行文件
gcc hello.c -o hello 直接編譯鏈接成可執(zhí)行目標(biāo)文件
gcc -c hello.c 或 gcc -c hello.c -o hello.o 編譯生成可重定位目標(biāo)文件
使用 gcc 時可以加上 -Wall 選項。下面這個例子如果不加上 -Wall 選項,編譯器不會報出任何錯誤或警告,但是程序的結(jié)果卻不是預(yù)期的:
//bad.c
#include stdio.h
int main()
printf(the number is %f ,5); // 程序輸出了 the number is 0.000000,結(jié)果錯誤
return 0;
}
使用 -Wall 選項:
gcc -Wall bad.c -o bad
gcc 將輸出警告信息:
warning: format ‘%f’ expects argument of type ‘double’, but argument 2 has type ‘int’ [-Wformat=]
printf(the number is %f\n ,5);
5、gcc 編譯多個文件
// hello.c
#include stdio.h
#include hello.h
void printHello()
printf(hello world!\n}
//main.c
#include stdio.h
#include hello.h
int main()
printHello();
return 0;
}
//hello.h
// 僅包含函數(shù)聲明
#ifndef _HELLO_
#define _HELLO_
void printHello();
#endif
編譯這三個文件,可以一次編譯:
gcc hello.c main.c -o main 生成可執(zhí)行文件 main
也可以獨立編譯:
gcc -Wall -c main.c -o main.o
gcc -Wall -c hello.c -o hello.o
gcc -Wall main.o hello.o -o main
獨立編譯的好處是,當(dāng)其中某個模塊發(fā)送改變時,只需要編譯該模塊就行,不必重新編譯所有文件,這樣可以節(jié)省編譯時間。
6、使用外部庫
在使用 C 語言和其他語言進(jìn)行程序設(shè)計的時候,我們需要頭文件來提供對常數(shù)的定義和對系統(tǒng)及庫函數(shù)調(diào)用的聲明。庫文件是一些預(yù)先編譯好的函數(shù)集合,那些函數(shù)都是按照可重用原則編寫的。它們通常由一組互相關(guān)聯(lián)的可重用原則編寫的,它們通常由一組互相關(guān)聯(lián)的用來完成某項常見工作的函數(shù)構(gòu)成。使用庫的優(yōu)點在于:
模塊化的開發(fā)
可重用性
可維護(hù)性
庫又可以分為靜態(tài)庫與動態(tài)庫:
靜態(tài)庫(.a):程序在編譯鏈接的時候把庫的代碼鏈接到可執(zhí)行文件中。程序運行的時候?qū)⒉辉傩枰o態(tài)庫。靜態(tài)庫比較占用磁盤空間,而且程序不可以共享靜態(tài)庫。運行時也是比較占內(nèi)存的,因為每個程序都包含了一份靜態(tài)庫。
動態(tài)庫(.so 或.sa):程序在運行的時候才去鏈接共享庫的代碼,多個程序共享使用庫的代碼,這樣就減少了程序的體積。
一般頭文件或庫文件的位置在:
/usr/include 及其子目錄底下的 include 文件夾
/usr/local/include 及其子目錄底下的 include 文件夾
/usr/lib
/usr/local/lib
/lib
7、生成靜態(tài)庫
為了生成.a 文件,我們需要先生成.o 文件。下面這行命令將我們的 hello.o 打包成靜態(tài)庫 libhello.a:
ar rcs libhello.a hello.o
ar 是 gun 歸檔工具,rcs 表示 replace and create,如果 libhello 之前存在,將創(chuàng)建新的 libhello.a 并將其替換。
然后就可以這樣來使用靜態(tài)庫 libhello.a
gcc -Wall main.c libhello.a -o main
還有另外一種使用方式:
gcc -Wall -L. main.c -o main -lhello 【lhello 是 libhello 的縮寫】
其中 -L. 表示庫文件的位置在當(dāng)前目錄下,由于 libhello.a 是我們自己生成的,并存放在當(dāng)前錄下下,所以需要加上 -L. 選項。默認(rèn)庫文件是在系統(tǒng)的目錄下進(jìn)行搜索。同樣的,-I. 選項用于頭文件的搜索。
8、生成共享庫
生成一個共享庫,名稱的規(guī)則是 libxxx.so。將剛才 hello.o 生成 libhello.so 的命令為:
gcc -shared -fPIC hello.o -o libhello.so
生成了共享庫之后,可以這樣來使用共享庫:
gcc -Wall main.o -o main -L. -lhello
該命令與使用靜態(tài)庫的命令相同,但是在共享庫與靜態(tài)庫共存的情況下,優(yōu)先使用共享庫。
共享庫有時候并不不在當(dāng)前的目錄下,為了讓 gcc 能夠找得到共享庫,有下面幾種方法:
拷貝.so 文件到系統(tǒng)共享庫路徑下,一般指 /usr/lib
在~/.bash_profile 文件中,配置 LD_LIBRARY_PATH 變量
配置 /etc/ld.so.conf,配置完成后調(diào)用 ldconfig 更新 ld.so.cache
其中,shared 選項表示生成共享庫格式。fPIC 表示產(chǎn)生位置無關(guān)碼(position independent code),位置無關(guān)碼表示它的運行、加載與內(nèi)存位置無關(guān),可以在任何內(nèi)存地址進(jìn)行加載。
9、庫的搜索路徑
庫的搜索路徑遵循幾個搜索原則:從左到右搜索 -I - l 指定的目錄,如果在這些目錄中找不到,那么 gcc 會從由環(huán)境 變量指定的目錄進(jìn)行查找。頭文件的環(huán)境變量是 C_INCLUDE_PATH, 庫的環(huán)境變量是 LIBRARY_PATH. 如果還是找不到,那么會從系統(tǒng)指定指定的目錄進(jìn)行搜索。
以上就是“l(fā)inux 里的 gcc 怎么使用”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,丸趣 TV 小編每天都會為大家更新不同的知識,如果還想學(xué)習(xí)更多的知識,請關(guān)注丸趣 TV 行業(yè)資訊頻道。