gcc使用总结
1.基本選項
-o 指定輸出文件名。如果不給出這個選項,gcc就給出預設的可執行文件a.out。
# cc? -o XX XX.c
-c
編譯、匯編到目標代碼,不進行鏈接
-v
打印較多信息,顯示編譯器調用的程序。
-E
僅作預處理,不進行編譯、匯編和鏈接。
-E 只激活預處理,這個不生成文件,你需要把它重定向到一個輸出文件里面.例子用法:gcc -E hello.c > pianoapan.txtgcc -E hello.c | more慢慢看吧,一個hello word 也要與處理成800行的代碼
-E選項,表示讓gcc只進行“預處理”就行了。 所謂的預處理,就是把程序中的宏展開, 把頭文件的內容展開包含進來等等一些編譯前的預處理操作。預處理結果會顯示到屏幕上,如果需要保存,則得需要重定向
-m32
-m64
生成32位/64位機器上的代碼。
2.gcc選項--調試
-g,生成調試信息。
# cc -g -o XX XX.c
-ggdb
-ggdblevel
為調試器 gdb 生成調試信息。level 可以為1,2,3,默認值為2。
-g
-glevel
生成操作系統本地格式的調試信息。-g 和 -ggdb 并不太相同, -g 會生成 gdb 之外的信息。level 取值同上。
3.gcc選項--匯編
-S 僅編譯到匯編語言,不進行匯編和鏈接。
# cc -S XX.c
4.gcc優化
-O0
禁止編譯器進行優化。默認為此項。
-O
-O1
嘗試優化編譯時間和可執行文件大小。
-O2
更多的優化,會嘗試幾乎全部的優化功能,但不會進行“空間換時間”的優化方法。
-O3
在 -O2 的基礎上再打開一些優化選項:-finline-functions, -funswitch-loops 和 -fgcse-after-reload 。
-Os
對生成文件大小進行優化。它會打開 -O2 開的全部選項,除了會那些增加文件大小的。
-finline-functions
把所有簡單的函數內聯進調用者。編譯器會探索式地決定哪些函數足夠簡單,值得做這種內聯。
-fstrict-aliasing
施加最強的別名規則(aliasing rules)。
# cc -o XX XX.c
5.gcc選項-Wall
-W是打開警告選項
-all打開所有
# cc -g -Wall -o XX XX.c
-Wall
會打開一些很有用的警告選項,建議編譯時加此選項。
-W
-Wextra
打印一些額外的警告信息。
-w
禁止顯示所有警告信息。
-Wshadow
當一個局部變量遮蓋住了另一個局部變量,或者全局變量時,給出警告。很有用的選項,建議打開。 -Wall 并不會打開此項。
-Wpointer-arith
對函數指針或者void *類型的指針進行算術操作時給出警告。也很有用。 -Wall 并不會打開此項。
-Wcast-qual
當強制轉化丟掉了類型修飾符時給出警告。 -Wall 并不會打開此項。
-Waggregate-return
如果定義或調用了返回結構體或聯合體的函數,編譯器就發出警告。
-Winline
無論是聲明為 inline 或者是指定了-finline-functions 選項,如果某函數不能內聯,編譯器都將發出警告。如果你的代碼含有很多 inline 函數的話,這是很有用的選項。
-Werror
把警告當作錯誤。出現任何警告就放棄編譯。
-Wunreachable-code
如果編譯器探測到永遠不會執行到的代碼,就給出警告。也是比較有用的選項。
-Wcast-align
一旦某個指針類型強制轉換導致目標所需的地址對齊增加時,編譯器就發出警告。
-Wundef
當一個沒有定義的符號出現在 #if 中時,給出警告。
-Wredundant-decls
如果在同一個可見域內某定義多次聲明,編譯器就發出警告,即使這些重復聲明有效并且毫無差別。
6.多個程序文件的編譯
通常整個程序是由多個源文件組成的,相應地也就形成了多個編譯單元,使用GCC能夠很好地管理這些編譯單元。假設有一個由test1.c和 test2.c兩個源文件組成的程序,為了對它們進行編譯,并最終生成可執行程序test,可以使用下面這條命令:
# cc test1.c test2.c -o test
如果同時處理的文件不止一個,GCC仍然會按照預處理、編譯和鏈接的過程依次進行。如果深究起來,上面這條命令大致相當于依次執行如下三條命令:
# cc -c test1.c -o test1.o
# cc -c test2.c -o test2.o
# cc test1.o test2.o -o test
7.gcc鏈接外部庫--I和L選項
-l library (僅對標準庫)
進行鏈接時搜索名為library的庫, -lm相當于libm.a。
例子: $ gcc test.c -lm -o test
-Idir
把dir 加入到搜索頭文件的路徑列表中。
例子: $ gcc test.c -I../inc -o test
-Ldir
把dir 加入到搜索庫文件的路徑列表中。
例子: $ gcc -I/home/foo -L/home/foo -ltest test.c -o test
?
8.線程庫
由于pthread庫不是Linux系統默認的庫,連接時需要使用庫libpthread.a,所以在使用pthread_create創建線程時,在編譯中要加-lpthread參數:
# gcc thread1.c -o thread1 -lpthread9.gcc選項--fpic
-fpic:產生位置無關碼
解釋一下,位置無關碼就是可以在進程的任意內存位置執行的目標碼,動態鏈接庫必須使用。
如果使用Makefile構建,一般要給CFLAGS中指定CFLAGS=-fPIC
10.gcc選項--共享
-shared
?
-static
?
11.使用Makefile構建
一般要給CFLAGS中指定-g
CFLAGS= -Wall -o2 -g
如果用configure腳本生成Makefile
#./configure CFLAGS= "-Wall -02 -g"
調試
#./configure CFLAGS= "-0 -g"
12.查看gcc版本
查看glibc版本
# rpm -qa | grep glibc
glibc-2.12-1.80.el6_3.6.x86_64
glibc-headers-2.12-1.80.el6_3.6.x86_64
glibc-devel-2.12-1.80.el6_3.6.x86_64
glibc-common-2.12-1.80.el6_3.6.x86_64
?
或者# ldd? --version
ldd (GNU libc) 2.12
?
查看gcc版本
# rpm -qa | grep gcc
gcc-gfortran-4.4.6-4.el6.x86_64
gcc-4.4.6-4.el6.x86_64
gcc-c++-4.4.6-4.el6.x86_64
libgcc-4.4.6-4.el6.x86_64
gcc-java-4.4.6-4.el6.x86_64
或者# gcc -v
使用內建 specs。
目標:x86_64-redhat-linux
配置為:../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --disable-libjava-multilib --with-ppl --with-cloog --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux
線程模型:posix
gcc 版本 4.4.6 20120305 (Red Hat 4.4.6-4) (GCC)
# man gcc
GCC編譯器的調用參數大約有100多個,其中多數參數我們可能根本就用不到
GCC設定include和庫路徑
一、頭文件
gcc 在編譯時尋找所需要的頭文件 :
※搜尋會從-I開始
※然后找gcc的環境變量 C_INCLUDE_PATH,CPLUS_INCLUDE_PATH,OBJC_INCLUDE_PATH (這些變量在windows下對應的是include環境變量)
※再找內定目錄
/usr/include
/usr/local/include
/usr/lib/gcc-lib/i386-linux/2.95.2/include
/usr/lib/gcc-lib/i386-linux/2.95.2/../../../../include/g++-3
/usr/lib/gcc-lib/i386-linux/2.95.2/../../../../i386-linux/include
庫文件但是如果裝gcc的時候,是有給定的prefix的話,那么就是
/usr/include
prefix/include
prefix/xxx-xxx-xxx-gnulibc/include
prefix/lib/gcc-lib/xxxx-xxx-xxx-gnulibc/2.8.1/include
二、庫文件
編譯的時候:
※gcc會去找-L
※再找gcc的環境變量LIBRARY_PATH
※再找內定目錄 /lib:/usr/lib: /usr/local/lib:這是當初compile gcc時寫在程序內的
三、運行時動態庫的搜索路徑
1、在配置文件/etc/ld.so.conf中指定動態庫搜索路徑
2、通過環境變量LD_LIBRARY_PATH指定動態庫搜索路徑(當通過該環境變量指定多個動態庫搜索路徑時,路徑之間用冒號":"分隔)(HP- UX對應的是SHLIB_PATH環境變量,AIX對應的是LIBPATH環境變量,windows對應的是lib環境變量)
3、在編譯目標代碼時指定該程序的動態庫搜索路徑(還可以在編譯目標代碼時指定程序的動態庫搜索路徑。
這是通過gcc 的參數"-Wl,-rpath,"指定。當指定多個動態庫搜索路徑時,路徑之間用冒號":"分隔
4、默認的動態庫搜索路徑/lib??? /usr/lib
可以通過執行可執行文件pos得到的結果不同獲知其搜索到了哪個動態庫,從而獲得第1個動態庫搜索順序,然后刪除該動態庫,
再執行程序pos,獲得第2個動態庫搜索路徑,再刪除第2個被搜索到的動態庫,
如此往復,將可得到Linux搜索動態庫的先后順序。
程序pos執行的輸出結果和搜索到的動態庫的對應關系如表1所示
程序pos輸出結果 使用的動態庫 對應的動態庫搜索路徑指定方式
./ ./libpos.so 編譯目標代碼時指定的動態庫搜索路徑
/root/test/env/lib /root/test/env/lib/libpos.so 環境變量LD_LIBRARY_PATH指定的動態庫搜索路徑
/root/test/conf/lib /root/test/conf/lib/libpos.so 配置文件/etc/ld.so.conf中指定的動態庫搜索路徑
/lib /lib/libpos.so 默認的動態庫搜索路徑/lib
/usr/lib /usr/lib/libpos.so 默認的動態庫搜索路徑/usr/lib
動態庫的搜索路徑搜索的先后順序是:
1.編譯目標代碼時指定的動態庫搜索路徑;
2.環境變量LD_LIBRARY_PATH指定的動態庫搜索路徑;
3.配置文件/etc/ld.so.conf中指定的動態庫搜索路徑;
4.默認的動態庫搜索路徑/lib??? /usr/lib。
?
// using –Wl,--rpath
#gcc main.c -ldl -Wl,—rpath=/home/username/usr/lib
總結
- 上一篇: 汇编语言使用C库函数和Linux动态链接
- 下一篇: GDB attach到进程