在Linux環境下進行開發,gcc是非常重要的編譯工具,所以學習gcc的基本常見用法時非常有必要的。
一.首先我們先說明下gcc編譯源文件的后綴名類型
.c為后綴的文件,C語言源代碼文件;
.a為后綴的文件,是由目標文件構成的檔案庫文件;
.C,.cc或.cxx 為后綴的文件,是C++源代碼文件;
.h為后綴的文件,是程序所包含的頭文件;
.i 為后綴的文件,是已經預處理過的C源代碼文件;
.ii為后綴的文件,是已經預處理過的C++源代碼文件;
.m為后綴的文件,是Objective-C源代碼文件;
.o為后綴的文件,是編譯后的目標文件;
.s為后綴的文件,是匯編語言源代碼文件;
.S為后綴的文件,是經過預編譯的匯編語言源代碼文件。
二.接下來,我們就具體介紹下gcc命令的具體用法了
gcc的基本命令格式是:gcc [options] [filenames]
其中[options]就是編譯器需要制定的相應選項,filenames就是相關文件的名稱,下面我就介紹下做常用的幾個options
(注意:一定要區分編譯選項里的大小寫,他們時代表不同的含義)
(1) -c :只是進行編譯而不連接成為可執行文件,編譯器只是由輸入的.c等源代碼文件生成.o為后綴的目標文件,通常用於編譯不包含主程序的子程序文件。
(2) -o output_filename :確定輸出的文件的名稱為output_filename,如果不給出這個選項,gcc就給出預設的可執行文件a.out。
(3) -g: 產生符號調試工具(GNU的gdb)所必要的符號信息,要想對源代碼進行調試,我們就必須加入這個選項。
(4) -O: 對程序進行優化編譯、連接,采用這個選項,整個源代碼會在編譯、連接過程中進行優化處理,這樣產生的可執行文件的執行效率可以提高,但是,編譯、連接的速度就相應地要慢一些。
(5) -O2 : 比-O更好的優化編譯、連接,當然整個編譯、連接過程會更慢。
(6) -Idirname: 將dirname所指出的目錄加入到程序頭文件目錄列表中,是在預編譯過程中使用的參數。
C程序中的頭文件包含兩種情況∶
a.#include <myinc.h>
b.#include "myinc.h"
其中a類時使用的是<>來包含頭文件,b類則使用“”來包含頭文件。他們之間的主要差別是:對於a類,預處理程序源文件在系統預設包含文件目錄(如/usr/include等等)中搜尋相應的文件,而對於b類,源文件則在當前目錄中搜尋頭文件,這個選項的作用是告訴源文件,如果在當前目錄中沒有找到需要的頭文件,就到指定的dirname目錄中去尋找。在程序設計中,如果我們需要的這種包含文件分別分布在不同的目錄中,就需要逐個使用-I選項給出搜索路徑。
(7) -Ldirname: 將dirname所指出的目錄加入到程序函數鏈接庫文件的目錄列表中,它是在連接過程中使用的參數。在預設狀態下,連接程序ld在系統的預設路徑中(如/usr/lib)尋找所需要的鏈接庫文件。而這個選項告訴連接程序,首先到-L指定的目錄中去尋找,然后再到系統預設路徑中尋找,如果函數庫存放在多個目錄下,就需要依次使用這個選項,給出相應的存放目錄。
(8) -lname: 程序在連接時,裝載名字為“libname.a”的函數庫,該函數庫位於系統預設的目錄或者由-L選項確定的目錄下。例如,-lm表示連接名為“libm.a”的數學函數庫,
"-lpthread"則表示鏈接線程函數鏈接庫文件。
(9) -shared:這主要是在生成共享庫文件時使用。
(10) -Wall : 生成所有警告信息。
(11) -w : 不生成任何警告信息。
(12) -S : 生成匯編語言文件。
三.最后,我還想向大家闡明下平時大家都沒怎么注意的一個問題-------gcc是怎么查找源文件中的頭文件和鏈接時所需的鏈接庫文件
(1) 查找頭文件
step1:在源文件所在的目錄下進行查找
step2:在我們在編譯程序用選項“-Idirname”所指的路徑去尋找頭文件。
step3:查找gcc相關的環境變量所設置的路徑:C_INCLUDE_PATH,CPLUS_INCLUDE_PATH,OBJC_INCLUDE_PATH
step4:查找gcc內定的目錄:
/usr/include
/usr/local/include
/usr/lib/gcc-lib/i386-linux/2.95.2/include
(2) 查找動態鏈接庫
什么時鏈接庫?我再羅嗦一句吧。就像我們C語言中常用的printf函數為例,你們知道printf函數是怎么實現的嗎?其實它是系統把這些函數實現都被做到名為libc.so.6的庫文件中去了,在沒有特別指定時,gcc會到系統默認的搜索路徑”/usr/lib”下進行查找,也就是鏈接到libc.so.6庫函數中去,這樣就能實現函數”printf”了,而這也就是鏈接的作用。其中函數庫又分為靜態函數庫和動態函數庫兩種。靜態庫是指編譯鏈接時,把庫文件的代碼全部加入到可執行文件中,因此生成的文件比較大,但在運行時也就不再需要庫文件了。其后綴名一般為”.a”。動態庫與之相反,在編譯鏈接時並沒有把庫文件的代碼加入到可執行文件中,而是在程序執行時由運行時鏈接文件加載庫,這樣可以節省系統的開銷。動態庫一般后綴名為”.so”,如前面所述的libc.so.6就是動態庫。
好了,言歸正傳,其實動態鏈接庫的查找過程其實和查找頭文件類似。
step1: 在選項“-Ldirname”所指定的目錄中查找。
step2: gcc的環境變量LIBRARY_PATH指定的路徑中查找。
step3: 在gcc內定的目錄中查找,如 /usr/lib/ /usr/local/lib/