Ⅰ、使用方法: gcc [選項] 文件名 Ⅱ、常用選項:提示:
gcc --help
Place the output into ;指定輸出文件名為file,這個名稱不能跟源文件名同名
-E
Preprocess only; do not compile, assemble or link;只預(yù)處理,不會編譯、匯編、鏈接
-S
Compile only; do not assemble or link;只編譯,不會匯編、鏈接
-c
Compile and assemble, but do not link; 編譯和匯編,不會鏈接
一個C/C++文件要經(jīng)過預(yù)處理(preprocessing)、編譯(compilation)、匯編(assembly)、和連接(linking)才能變成可執(zhí)行文件。
以下列程序為例,追層來分析編譯過程。
hello.c:
#include
#define MAX 20
#define MIN 10
#define _DEBUG
#define SetBit(x) (1<
① 預(yù)處理:
gcc -E -o hello.i hello.c
預(yù)處理就是將要包含(include)的文件插入原文件中、將宏定義展開、根據(jù)條件編譯命令選擇要使用的代碼,最后將這些代碼輸出到一個“.i”文件中等待進(jìn)一步處理。 ② 編譯:
gcc -S -o hello.s hello.i
編譯就是把C/C++代碼(比如上面的”.i”文件)“翻譯”成匯編代碼。
③ 匯編:
gcc -c -o hello.o hello.s
匯編就是將第二步輸出的匯編代碼翻譯成符合一定格式的機(jī)器代碼,在Linux系統(tǒng)上一般表現(xiàn)位ELF目標(biāo)文件(OBJ文件)。 ④ 鏈接:.o:object file(OBJ文件) 這里表現(xiàn)為二進(jìn)制目標(biāo)文件:
gcc -o hello hello.o
鏈接就是將匯編生成的OBJ文件、系統(tǒng)庫的OBJ文件、庫文件鏈接起來,最終生成可以在特定平臺運(yùn)行的可執(zhí)行程序。 總結(jié):在編譯過程中。除非使用了”-c”,“-S”,或”-E”選項(或者編譯錯誤阻止了完整的過程),否則統(tǒng)一完整鏈接步驟。
譬如:gcc hello.c 和gcc -o hello hello.c都已經(jīng)完成鏈接操作。
又如:gcc -c -o hello.o hello.c
gcc -c -o hello.o hello.c 不作最后一步鏈接,得到hello.o二進(jìn)制OBJ文件
gcc -v -o hello hello.o 我們來看一樣鏈接過程是怎樣的:
book@www.100ask.org:/work/gcc_options/1th$ gcc -v -o hello hello.o
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/5/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 5.4.0-6ubuntu1~16.04.4' --with-bugurl=file:///usr/share/doc/gcc-5/README.Bugs --enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-5 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-5-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-5-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-5-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4)
COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/5/:/usr/lib/gcc/x86_64-linux-gnu/5/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/5/:/usr/lib/gcc/x86_64-linux-gnu/
LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/5/:/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/5/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/5/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-v' '-o' 'hello' '-mtune=generic' '-march=x86-64'
/usr/lib/gcc/x86_64-linux-gnu/5/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/5/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/5/lto-wrapper -plugin-opt=-fresolution=/tmp/ccbhavbV.res
-plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s
-plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc
-plugin-opt=-pass-through=-lgcc_s --sysroot=/ --build-id
--eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed
-dynamic-linker /lib64/ld-linux-x86-64.so.2 -z relro
-o hello
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crti.o
/usr/lib/gcc/x86_64-linux-gnu/5/crtbegin.o
-L/usr/lib/gcc/x86_64-linux-gnu/5
-L/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu
-L/usr/lib/gcc/x86_64-linux-gnu/5/../../../../lib
-L/lib/x86_64-linux-gnu -L/lib/../lib
-L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib
-L/usr/lib/gcc/x86_64-linux-gnu/5/../../..
hello.o
-lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed
/usr/lib/gcc/x86_64-linux-gnu/5/crtend.o
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crtn.o
book@www.100ask.org:/work/gcc_options/1th$
crt1.o、crti.o、crtbegin.o、crtend.o、crtn.o是gcc加入的系統(tǒng)標(biāo)準(zhǔn)啟動文件,對于一般應(yīng)用程序,這些啟動是必需的。
-lc:鏈接libc庫文件,其中l(wèi)ibc庫文件中就實現(xiàn)了printf等函數(shù)。
① 動態(tài)鏈接:動態(tài)鏈接使用動態(tài)鏈接庫進(jìn)行鏈接,生成的程序在執(zhí)行的時候需要加載所需的動態(tài)庫才能運(yùn)行。 動態(tài)鏈接生成的程序體積較小,但是必須依賴所需的動態(tài)庫,否則無法執(zhí)行。
② 靜態(tài)鏈接:靜態(tài)鏈接使用靜態(tài)庫進(jìn)行鏈接,生成的程序包含程序運(yùn)行所需要的全部庫,可以直接運(yùn)行,不過靜態(tài)鏈接生成的程序體積較大。默認(rèn)使用動態(tài)鏈接:
gcc -o hello_shared hello.o
③ -nostartfiles
gcc -static -o hello_static hello.o
④ -nostdlib(最常用)不鏈接系統(tǒng)標(biāo)準(zhǔn)啟動文件,而標(biāo)準(zhǔn)庫文件仍然正常使用:
gcc -v -nostartfiles -o hello hello.o
不鏈接系統(tǒng)標(biāo)準(zhǔn)啟動文件和標(biāo)準(zhǔn)庫文件:
gcc -v -nostdlib -o hello hello.o
- 會提示因為沒有鏈接系統(tǒng)標(biāo)準(zhǔn)啟動文件和標(biāo)準(zhǔn)庫文件,而鏈接失敗。
- 這個-nostdlib選項常用于裸機(jī)/bootloader、linux內(nèi)核等程序,因為它們不需要啟動文件、標(biāo)準(zhǔn)庫文件。





