GCC/Clang編譯器淺談
GCC和Clang編譯器淺談
GCC是Linux上使用的編譯器,Clang是Mac上使用的編譯器,兩者命令格式基本相同,這裡筆者對編譯器做一個淺談(筆者使用的是macbook,所以程式碼以macbook上的命令為例)。
首先寫一個編譯的語句:
gcc/clang -g -O2 -o test test.c -I... -L... -l
這是一條對test.c進行編譯最終的到可執行檔案的語句,下面逐個解釋一下語句中各個命令的用法。
-g:輸出檔案中的除錯資訊。我們的程式在執行中如果出現問題,我們就可以用偵錯程式對其進行除錯。 -O2:對輸出的檔案做指令優化。對應預設的O1,我們在不寫的情況下預設是O1,這樣我們在除錯的時候,每一步的臨時變數是可以顯示出來的。但是,如果設定成了O2,那麼就不會顯示出來。一般O2應用在上線版本,可以讓編譯器自己選擇優化掉一些不必要的資訊,這樣能更快速的執行程式;而O1一般用於未上線的程式碼,讓我們可以進行除錯。 -o:輸出檔案。後面接要編譯成的檔名和被編譯的檔名。 -I:指定標頭檔案位置。在使用第三方庫或者我們寫的標頭檔案時,就要告訴編譯器標頭檔案的目錄。 -L:指定庫檔案位置。 -l:指定使用哪個庫。比-L更具體。-L好比給了一堆庫,-l指定用哪個。
編譯過程
預編譯:將標頭檔案和原始碼聯絡在一起,並未編譯,只是為編譯做準備。 編譯:將程式碼編譯成.o檔案。不是可執行檔案,只是一箇中間檔案,還需要進行連結。 連結(動態連結/靜態連結):與系統或者第三方庫進行連結。 靜態連結:將所有的庫連結在一起,形成一個特別大的檔案。 動態連結:在程式碼執行過程中進行連結。
舉個例子:我們將自己寫的一個.c程式程式設計一個庫檔案,然後在main函式中呼叫這個庫檔案(比較類似於java中呼叫另一個類的方法,只不過C語言中沒有類的概念,並且呼叫方式比java複雜一些)。
具體步驟:
1. 將我們自己的.c檔案編譯成.o中間檔案,
2. 將.o檔案編譯成一個庫檔案。
3. 在main函式中呼叫這個庫檔案。
1. add.c程式碼 #ifndef __MYLIBRARY__ #define __MYLIBRARY__ int add(int a, int b){ return a+b; } #endif //__MY_LIBRARY__ add.h程式碼 #ifndef __MY_LIBRARY__ #define __MY_LIBRARY__ int add(int a, int b) #endif 然後我們在控制檯執行"clang -g -c add.c"得到add.o中間檔案。 2. 使用語句"libtool -static -o libmylib.a add.o"將add.o編譯成mylib.a庫檔案。 -static:意思是編譯成一個靜態庫 libmylib:這裡需要注意的一點是"mylib"其實是我們的名字,但是根據規則,在我們起的名字前面必須加上一個"lib"作為字首。 3. 我們寫一個帶main函式的程式碼test.c呼叫這個mylib庫 #include <stdio.h> #include "add.h" int main(int argc, char* argv[]){ printf("add = %d\n", add(3, 3)); return 0; } 然後在控制檯使用我們最上面的語句編譯這段程式碼: clang -g -o test test.c -I . -L . -lmylib "."代表當前目錄 最後在控制檯呼叫"./test"就可以得到輸出的結果。