gcc的基本用法
指令格式:gcc [選項] [檔案名]
編譯的四個階段:
-E:僅執行編譯預處理;
-c:僅執行編譯操作,不進行連接配接操作;
-S:将C代碼轉換為彙編代碼;
-o:指定生成的輸出檔案。
–c是使用GNU彙編器将源檔案轉化為目标代碼之後就結束,在這種情況下,隻調用了C編譯器(ccl)和彙編器(as),而連接配接器(ld)并沒有被執行,是以輸出的目标檔案不會包含作為Linux程式在被裝載和執行時所必須的包含資訊,但它可以在以後被連接配接到一個程式
-c表示隻編譯(compile),而不連接配接成為可執行檔案。生成同名字的 .o 目标檔案。通常用于編譯不包含主程式的子程式檔案。
gcc -c hello.c
生成:hello.o
-o選項用于說明輸出(output)檔案名,gcc将生成一個目标(object)檔案xx。
gcc hello.c -o xqf
或者:gcc -o xqf hello.c(順序可以調換)
輸出:xqf 為程式可執行檔案
-g 選項産生符号調試工具(GNU的gdb)所必要的符号資訊,插入到生成的二進制代碼中。表示編譯DEBUG版本。
想要對源代碼進行調試,就必須加入這個選項。當然,會增加可執行檔案的大小。
gcc study.c -o xqf
gcc -g study.c -o xqf_g
結果如下:(确實加了 -g 可執行檔案後變大了一點)
-rwxr-xr-x 1 root root 12393 Apr 19 21:39 xqf_g
-rwxr-xr-x 1 root root 11817 Apr 19 20:48 xqf
gcc 在産生調試符号時,同樣采用了分級的思路,開發人員可以通過在 -g 選項後附加數字1、2、3指定在代碼中加入調試資訊的多少。預設的級别是2(-g2),此時産生的調試資訊包括:擴充的符号表、行号、局部或外部變量資訊。
級别3(-g3)包含級别2中的所有調試資訊以及源代碼中定義的宏。
級别1(-g1)不包含局部變量和與行号有關的調試資訊,是以隻能夠用于回溯跟蹤和堆棧轉儲。
回溯追蹤:指的是監視程式在運作過程中函數調用曆史。
堆棧轉儲:則是一種以原始的十六進制格式儲存程式執行環境的方法。
-pedantic 選項:當gcc在編譯不符合ANSI/ISO C 語言标準的源代碼時,将産生相應的警告資訊
[objc]
view plain
copy
#include <stdio.h>
int main()
{
long long int var = 1;
"hello world!\n");
return 0;
}
gcc -pedantic -o mm study.c
study.c: In function ‘main’:
study.c:5: warning: ISO C90 does not support ‘long long’
-Wall選項:使gcc産生盡可能多的警告資訊,警告資訊很有可能是錯誤的來源,特别是隐式程式設計錯誤,是以盡量保持0 warning。
用上面的代碼:study.c,編譯如下
gcc -Wall -o he study.c
study.c: In function ‘main’:
study.c:5: warning: unused variable ‘var’
-Werror 選項:要求gcc将所有的警告當作錯誤進行處理。
同樣是上面的程式:study.c
gcc -Werror -o haha study.c
竟然沒有錯誤!!
改一下study.c
#include <stdio.h>
[objc]
view plain
copy
{
long long int var = 1;
"hello world!\n");
//return 0;
}
再編譯:
gcc -Werror -o haha study.c
cc1: warnings being treated as errors
study.c: In function ‘main’:
study.c:4: error: return type of ‘main’ is not ‘int’
gcc -Wall -o hehe study.c
study.c:3: warning: return type of ‘main’ is not ‘int’
study.c: In function ‘main’:
study.c:5: warning: unused variable ‘var’
是以說:并不是所有的warning都變成 error。具體的,後面再深究。
-fPIC選項。PIC指Position Independent Code。共享庫要求有此選項,以便實作動态連接配接(dynamic linking)。
-I 選項(大寫的 i):向頭檔案搜尋目錄中添加新的目錄。
1、用#include"file"的時候,gcc/g++會先在目前目錄查找你所制定的頭檔案,如
果沒有找到,他回到預設的頭檔案目錄找。
如果使用-I制定了目錄,他會先在你所制定的目錄查找,然後再按正常的順序去找.
2、用#include<file>,gcc/g++會到-I制定的目錄查找,查找不到,然後将到系統的缺
省的頭檔案目錄查找
例如:
gcc –I /usr/dev/mysql/include test.c –o test.o
-l選項(小寫的 l)說明庫檔案的名字。如果庫檔案為 libtest.so, 則選項為: -ltest
-L選項說明庫檔案所在的路徑。
例如:-L.(“.”表示目前路徑)。
-L/usr/lib (“/usr/lib” 為路徑。注:這裡的路徑是絕對路徑)
如果沒有提供 -L選項,gcc 将在預設庫檔案路徑下搜尋
-shared選項指定生成動态連接配接庫,不用該标志外部程式無法連接配接。相當于一個可執行檔案, 生成 .so 檔案
-static 選項,強制使用靜态連結庫,生成 .a 檔案。因為gcc在連結時優先選擇動态連結庫,隻有當動态連結庫不存在時才使用靜态連結庫。加上該選項可強制使用靜态連結庫。
.so 和 .a 的差別:運作時動态加載,編譯時靜态加載
具體的例子在文章:linux so檔案生成與連結中有講。
多個檔案一起編譯:
檔案:test_a.c test_b.c
兩種編譯方法:
1、一起編譯
gcc test_a.c test_b.c -o test
2、分别編譯各個源檔案,之後對編譯後輸出的目标檔案連結
gcc -c test_a.c
gcc -c test_b.c
gcc -o test_a.o test_b.o -o test
比較:第一中方法編譯時需要所有檔案重新編譯;第二種植重新編譯修改的檔案,未修改的不用重新編譯