gcc選項和擴展

-c

指定源代碼只編譯不鏈接.

如:

gcc  -c  -o  a.o   a.c

編譯成a.o目標工程文件.

-D

定義宏

gcc  -DDIR = "/root"  -o  a  a.c

-Idir

將目錄dir加入到頭文件搜尋的路徑中

-Ldir

將目錄dir加入到搜尋庫的目錄中

-llibhello.so

鏈接到libhello.so共享庫,注意這裏使用的是-l參數

-static

只鏈接靜態庫

-g,-ggdb

包含調試信息

-O

優化

-Wall

打開所有並且有用的警告信息.

下面是摘錄網絡上的:來源:http://blog.sina.com.cn/s/blog_4d6b1457010099ea.html

The History of GCC


1984年,Richard Stallman發起了自由軟件運動,GNU (Gnu's Not Unix)項目應運而生,3年後,最初版的GCC橫空出世,成爲第一款可移植、可優化、支持ANSI C的開源C編譯器。
GCC最初的全名是GNU C Compiler,之後,隨着GCC支持的語言越來越多,它的名稱變成了GNU Compiler Collection。
這裏介紹的gcc是GCC的前端,C編譯器.
 


警告信息


    -Wall : 顯示所有常用的編譯警告信息。
    -W    : 顯示更多的常用編譯警告,如:變量未使用、一些邏輯錯誤。
    -Wconversion : 警告隱式類型轉換。
    -Wshadow : 警告影子變量(在代碼塊中再次聲明已聲明的變量)
    -Wcast-qual :警告指針修改了變量的修飾符。如:指針修改const變量。
    -Wwrite-strings : 警告修改const字符串。
    -Wtraditional : 警告ANSI編譯器與傳統C編譯器有不同的解釋。
    -Werror : 即使只有警告信息,也不編譯。(gcc默認:若只有警告信息,則進行編譯,若有錯誤信息,則不編譯)
 


C語言標準


你可以在gcc的命令行中通過指定選項來選擇相應的C語言標準: 從傳統c到最新的GNU擴展C. 默認情況下, gcc使用最新的GNU C擴展.

    -ansi : 關閉GNU擴展中與ANSI C相抵觸的部分。
    -pedantic          : 關閉所有的GNU擴展。
    -std=c89           : 遵循C89標準
    -std=c99           : 遵循C99標準
    -std=traditional : 使用原始C
注意:後4個選項可以與-ansi結合使用,也可以單獨使用。

可在gcc中使用大量GNU C擴展.

 

生成特定格式的文件


以hello.c爲例子,可以設置選項生成hello.i, hello.s, hello.o以及最終的hello文件:

    hello.c : 最初的源代碼文件;
    hello.i : 經過編譯預處理的源代碼;
    hello.s : 彙編處理後的彙編代碼;
    hello.o : 編譯後的目標文件,即含有最終編譯出的機器碼,但它裏面所引用的其他文件中函數的內存位置尚未定義。
    hello / a.out : 最終的可執行文件
    (還有.a(靜態庫文件), .so(動態庫文件), .s(彙編源文件)留待以後討論)
 

如果你不通過-o指定生成可執行文件名,那麼會默認生成a.out. 不指定生成文件名肯能覆蓋你上次生成的a.out.
 

e.g.
$ gcc hello.c
在不給gcc傳遞任何參數的情況下, gcc執行默認的操作: 將源文件編譯爲目標文件--> 將目標文件連接爲可執行文件(名爲a.out) --> 刪除目標文件.
 

-c生成.o文件時,默認生成與源代碼的主幹同名的.o文件。比如對應hello.c生成hello.o. 但也可在生成目標文件時指定目標文件名(注意同時要給出.o後綴): $ gcc -c -o demo.o demo.c
 

    $ gcc -Wall -c hello.c              : 生成hello.o
    $ gcc -Wall -c -save-temps hello.c  : 生成hello.i, hello.s, hello.o
    注意-Wall 選項的使用場合:僅在涉及到編譯(即會生成.o文件時,用-Wall)  
 

多文件編譯、連接
 


如果原文件分佈於多個文件中:file1.c, file2,c
    $ gcc -Wall file1.c file2.c -o name

若對其中一個文件作了修改,則可只重新編譯該文件,再連接所有文件:
    $ gcc -Wall -c file2.c
    $ gcc file1.c file2.o -c name

注意:若編譯器在命令行中從左向右順序讀取.o文件,則它們的出現順序有限制:含有某函數定義的文件必須出現在含有調用該函數的文件之後。好在GCC無此限制。


 

編譯預處理


以上述的hello.c爲例, 要對它進行編譯預備處理, 有兩種方法: 在gcc中指定-E選項, 或直接調用cpp.gcc的編譯預處理命令程序爲cpp,比較新版本的gcc已經將cpp集成了,但仍提供了cpp命令. 可以直接調用cpp命令, 也可以在gcc中指定-E選項指定它只進行編譯預處理.

$ gcc -E hello.c                            ==  $ cpp hello.c
上述命令馬上將預處理結果顯示出來. 不利於觀看. 可採用-c將預處理結果保存:
$ gcc -E -c hello.i hello.c              ==  $ cpp -o hello.i hello.c
注意, -c指定名稱要給出".i"後綴.

另外, gcc針對編譯預處理提供了一些選項:
(1) 除了直接在源代碼中用 #define NAME來定義宏外,gcc可在命令行中定義宏:-DNAME(其中NAME爲宏名), 也可對宏賦值: -DNAME=value 注意等號兩邊不能有空格! 由於宏擴展只是一個替換過程,也可以將value換成表達式,但要在兩邊加上雙括號: -DNAME="statement"
e.g. $ gcc -Wall -DVALUE="2+2" tmp.c -o tmp
如果不顯示地賦值,如上例子,只給出:-DVALUE,gcc將使用默認值:1.

(2) 除了用戶定義的宏外, 有一些宏是編譯器自動定義的,它們以__開頭,運行: $ cpp -dM /dev/null, 可以看到這些宏. 注意, 其中含有不以__開頭的非ANSI宏,它們可以通過-ansi選項被禁止。
 
查看宏擴展
1, 運行 $ gcc -E test.c ,gcc對test.c進行編譯預處理,並立馬顯示結果. (不執行編譯) 2, 運行 $ gcc -c -save-temps test.c ,不光產生test.o,還產生test.i, test.s,前者是編譯預處理結果, 後者是彙編結果
  利用Emacs查看編譯預處理結果
針對含有編譯預處理命令的代碼,可以利用emacs方便地查看預處理結果,而不需執行編譯,更爲方便的是,可以只選取一段代碼,而非整個文件:
1,選擇想要查看的代碼
2,C-c C-e (M-x c-macro-expand)
這樣,就自動在一個名爲"Macroexpansion"的buffer中顯示pre-processed結果.

生成彙編代碼


使用"-S"選項指定gcc生成以".s"爲後綴的彙編代碼:
$ gcc -S hello.c
$ gcc -S -o hello.s hello.c

生成彙編語言的格式取決於目標平臺. 另外, 如果是多個.c文件, 那麼針對每一個.c文件生成一個.s文件.
調試

一般地,可執行文件中是不包含任何對源代碼的參考的,而debugger要工作,就要知道目標文件/可執行文件中的機器碼對應的源代碼的信息(如:哪條語 句、函數名、變量名...). debugger工作原理:將函數名、變量名,對它們的引用,將所有這些對象對應的代碼行號儲存到目標文件或可執行文件的符 號表中。

GCC提供-g選項,將調試信息加入到目標文件或可執行文件中。
$ gcc -Wall -g hello.c -o hello

注意:若發生了段錯誤,但沒有core dump,是由於系統禁止core文件的生成!
$ ulimit -c  ,若顯示爲0,則系統禁止了core dump
 

解決方法:
$ ulimit -c unlimited  (只對當前shell進程有效)
或在~/.bashrc 的最後加入: ulimit -c unlimited (一勞永逸)
 

優化


GCC具有優化代碼的功能,代碼的優化是一項比較複雜的工作,它可歸爲:源代碼級優化、速度與空間的權衡、執行代碼的調度。

GCC提供了下列優化選項:
    -O0  : 默認不優化(若要生成調試信息,最好不優化)
    -O1  : 簡單優化,不進行速度與空間的權衡優化;   
    -O2  : 進一步的優化,包括了調度。(若要優化,該選項最適合,它是GNU發佈軟件的默認優化級別;
    -O3  : 雞肋,興許使程序速度更慢;
    -funroll-loops  : 展開循環,會使可執行文件增大,而速度是否增加取決於特定環境;
    -Os  : 生成最小執行文件;

一般來說,調試時不優化,一般的優化選項用-O2(gcc允許-g與-O2聯用,這也是GNU軟件包發佈的默認選項),embedded可以考慮-Os。

注意:此處爲O!(非0或小寫的o,-o是指定可執行文件名)。

檢驗優化結果的方法:$ time ./prog

time測量指定程序的執行時間,結果由三部分組成:
    real : 進程總的執行時間, 它和系統負載有關(包括了進程調度,切換的時間)
    user: 被測量進程中用戶指令的執行時間
    sys  : 被測量進程中內核代用戶指令執行的時間

user和sys的和被稱爲CPU時間.

注意:對代碼的優化可能會引發警告信息,移出警告的辦法不是關閉優化,而是調整代碼。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章