linux gcc编译C程序 分享
1) 預處理:把c文件中預處理命令掃描處理完畢,即對源代碼文件中的文件包含(#include)、預編譯語句(如宏定義#define等)進行分析,此時生成的文件仍然是可讀的。
2) 編譯:把預處理后的結果編譯成匯編或者目標模塊,即生成匯編語言文件,此時生成的文件仍然是可讀的匯編文件。
3) 匯編:把編譯出來的結果匯編成具體CPU上的目標代碼模塊,也即此時轉換成具體的機器語言代碼,此時生成的文件是不可讀的非文本文件。
4) 連接:把多個目標代碼模塊連接生成一個大的目標模塊,即將多個上面產生的機器代碼文件(與其它的機器代碼文件和庫文件)匯集成一個可執行的二進制代碼文件。
??? gcc作為c語言在linux下很著名的編譯軟件,分別有如下option來支持4個步驟:
? 名稱 ? ? ? ? ? ? ? gcc選項英文名稱??????? ? ? ? ? ?? gcc調用的程序示例
? 預處理? -E?????? Pre-Processing??cpp???????????? gcc -E test.c -o test.i
? 編譯? -S????????? Compiling???????? ccl?????????????? gcc -S test.i? -o test.s?
? 匯編? -c????????? Assembling??????? as?????????????? gcc -c test.s? -o test.o
? 連接? 無????????? Linking????????????? ld??????????? ? ? gcc???? test.o? -o test
說明:
??gcc在編譯c語言文件時,首先調用cpp進行預處理,在預處理過程中,對源代碼文件中的文件包含(#include)、預編譯語句(如宏定義#define等)進行分析;其次調用ccl進行編譯工作,將文件編譯成匯編語言文件,此時文件依舊是可讀的;之后調用as進行匯編工作,將具體的匯編語言文件編譯成cpu可執行的目標代碼,此時文件不可讀了;當所有的目標文件都生成之后,gcc就調用ld來完成最后的關鍵性工作,鏈接。在鏈接階段,所有的目標文件被安排在可執行程序中的恰當的位置,同時,該程序所調用到的庫函數也從各自所在的庫中鏈接到合適的地方。下面對上面4個過程做下分別的說明:
1、在預處理階段,如果不用“-o”指定文件名,那么會默認將預處理結果輸出到標準終端設備。
[root@dbbak tmp]# cat a.c
int main()
{
??????? printf("shengtong test!\n");
}
[root@dbbak tmp]# gcc -E a.c
# 1 "a.c"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "a.c"
int main()
{
??????? printf("shengtong test!\n");
}
[root@dbbak tmp]# gcc -E a.c -o a.i
[root@dbbak tmp]# cat a.i
# 1 "a.c"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "a.c"
int main()
{
??????? printf("shengtong test!\n");
}
2、在編譯階段,如果不用“-o”指定文件名,那么默認會生成一個“*.s”的匯編語言文件。
[root@dbbak tmp]# gcc -S a.i
[root@dbbak tmp]# ls
a.c? a.i? a.s
[root@dbbak tmp]# gcc -S a.i -o a1.s
[root@dbbak tmp]# ls
a.c? a.i? a.s? a1.s
[root@dbbak tmp]#
[root@dbbak tmp]# cat a.s
??????? .file?? "a.c"
??????? .section??????? .rodata
.LC0:
??????? .string "shengtong test!\n"
??????? .text
.globl main
??????? .type?? main,@function
main:
??????? pushl?? %ebp
??????? movl??? %esp, %ebp
??????? subl??? $8, %esp
??????? andl??? $-16, %esp
??????? movl??? $0, %eax
??????? subl??? %eax, %esp
??????? subl??? $12, %esp
??????? pushl?? $.LC0
??????? call??? printf
??????? addl??? $16, %esp
??????? leave
??????? ret
.Lfe1:
??????? .size?? main,.Lfe1-main
??????? .section??????? .note.GNU-stack,"",@progbits
??????? .ident? "GCC: (GNU) 3.2.3 20030502 (Red Hat Linux 3.2.3-42)"
[root@dbbak tmp]# cat a1.s
??????? .file?? "a.c"
??????? .section??????? .rodata
.LC0:
??????? .string "shengtong test!\n"
??????? .text
.globl main
??????? .type?? main,@function
main:
??????? pushl?? %ebp
??????? movl??? %esp, %ebp
??????? subl??? $8, %esp
??????? andl??? $-16, %esp
??????? movl??? $0, %eax
??????? subl??? %eax, %esp
??????? subl??? $12, %esp
??????? pushl?? $.LC0
??????? call??? printf
??????? addl??? $16, %esp
??????? leave
??????? ret
.Lfe1:
??????? .size?? main,.Lfe1-main
??????? .section??????? .note.GNU-stack,"",@progbits
??????? .ident? "GCC: (GNU) 3.2.3 20030502 (Red Hat Linux 3.2.3-42)"
3、在匯編階段,如果不用“-o”指定文件名,那么默認會生成一個“*.o”的機器語言代碼文件。
[root@dbbak tmp]# gcc -c a.s
[root@dbbak tmp]# ls
a.c? a.i? a.o? a.s? a1.s
[root@dbbak tmp]# gcc -c a1.s -o a1.o
[root@dbbak tmp]# ls
a.c? a.i? a.o? a.s? a1.o? a1.s
[root@dbbak tmp]#
[root@dbbak tmp]# file a.o
a.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
[root@dbbak tmp]# file a1.o
a1.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
4、在連接階段,不指定前面3個選項就是默認進入這個階段,如果不用“-o”指定文件名,那么默認會生產一個“a.out”的可執行文件。
[root@dbbak tmp]# gcc a.o
[root@dbbak tmp]# ls
a.c? a.i? a.o? a.out? a.s? a1.o? a1.s? -- 可執行文件
[root@dbbak tmp]# gcc a1.o -o a1.out
[root@dbbak tmp]# ls
a.c? a.i? a.o? a.out? a.s? a1.o? a1.out? a1.s
[root@dbbak tmp]#
[root@dbbak tmp]# ./a.out
shengtong test!
[root@dbbak tmp]# ./a1.out
shengtong test!
5、編譯c文件的時候,可以跳過前面階段而直接進入后面階段,如可以不分開執行預處理命令gcc -E test.c,而直接進入編譯環節gcc -S test.c -o test.s,gcc會在執行“編譯”環節(后面階段)的時候發現沒有“預編譯”環節(前面階段),它會自動補上。
?
??? gcc能夠編譯的語言文件有很多(常見的如c語言和c++語言等),它默認情況下依據文件的后綴名執行相應的編譯,下面列出c和c++的:
.c 為后綴的文件,C語言源代碼文件;
.i 為后綴的文件,是已經預處理過的C源代碼文件;
.s 為后綴的文件,是匯編語言源代碼文件;
.o 為后綴的文件,是編譯后的目標文件;
.h 為后綴的文件,是程序所包含的頭文件;
.a 為后綴的文件,是由目標文件構成的庫文件;
.C .cc .cp .cpp .c++ .cxx 為后綴的文件,是C++源代碼文件;
.ii 為后綴的文件,是已經預處理過的C++源代碼文件;
.m 為后綴的文件,是Objective-C源代碼文件;
.mi 是已經預處理過的Objective-C源代碼文件;
.S 為后綴的文件,是經過預編譯的匯編語言源代碼文件。
??? 當然,你可以亂寫自己的文件名后綴,如將c文件以.cpp結尾或者以.eng結尾,那么gcc就無法根據后綴名來做正確的編譯了,此時怎么辦?gcc提供了“-x”選項來指定文件類型,“-x”選項內容有(只列出c和c++的):
c? c-header? cpp-output
c++? c++-cpp-output
objective-c? objc-cpp-output
assembler? assembler-with-cpp
??? 當使用了“-x”選項后,那么其后面所有的文件都默認是其指定的文件類型,直到用“-x none”來指定結束。
[root@dbbak tmp]# gcc -x c -E a.sql -o a.i
[root@dbbak tmp]# cat a.i
# 1 "a.sql"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "a.sql"
int main()
{
??????? printf("shengtong test!\n");
}
[root@dbbak tmp]# mv c.sql c.c
[root@dbbak tmp]#
[root@dbbak tmp]# gcc -x c -S a.sql b.sql -x none? -S c.c
[root@dbbak tmp]# ls
a.i? a.s? a.sql? b.s? b.sql? c.c? c.s
??
????下面再介紹下gcc的其他常用選項:
??? -pass-exit-codes
??? Normally the gcc program will exit with the code of 1 if any phase of the compiler returns a non-success return code.? If you specify -pass-exit-codes, the gcc program will instead return with numeri-cally highest error produced by any phase that returned an error indication.
通常如果編譯器遇到錯誤,返回值1;如果你想返回具體的錯誤代碼,請用它。
????
??? -o file
??? Place output in file file.? This applies regardless to whatever sort of output is being produced, whether it be an executable file,an object file, an assembler file or preprocessed C code.
??? Since only one output file can be specified, it does not make sense to use -o when compiling more than one input file, unless you are producing an executable file as output.
??? If -o is not specified, the default is to put an executable file in a.out, the object file for source.suffix in source.o, its assembler file in source.s, and all preprocessed C source on standard output.? -- 這段話我在上面的1/2/3/4/5中已經介紹了
????
???? -v?
??? Print (on standard error output) the commands executed to run the stages of compilation.? Also print the version number of the com-piler driver program and of the preprocessor and the compiler proper.
????這個選項的作用是把gcc編譯c文件的過程給打印出來,如下面這個例子:
[root@dbbak tmp]# gcc -v a.c
Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/3.2.3/specs
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --disable-checking --with-system-zlib --enable-__cxa_atexit --host=i386-redhat-linux
Thread model: posix
gcc version 3.2.3 20030502 (Red Hat Linux 3.2.3-42)
?/usr/lib/gcc-lib/i386-redhat-linux/3.2.3/cc1 -lang-c -v -D__GNUC__=3 -D__GNUC_MINOR__=2 -D__GNUC_PATCHLEVEL__=3 -D__GXX_ABI_VERSION=102 -D__ELF__ -Dunix -D__gnu_linux__ -Dlinux -D__ELF__ -D__unix__ -D__gnu_linux__ -D__linux__ -D__unix -D__linux -Asystem=posix -D__NO_INLINE__ -D__STDC_HOSTED__=1 -Acpu=i386 -Amachine=i386 -Di386 -D__i386 -D__i386__ -D__tune_i386__ a.c -quiet -dumpbase a.c -version -o /tmp/cclLW8Ji.s
GNU CPP version 3.2.3 20030502 (Red Hat Linux 3.2.3-42) (cpplib) (i386 Linux/ELF)
GNU C version 3.2.3 20030502 (Red Hat Linux 3.2.3-42) (i386-redhat-linux)
??????? compiled by GNU C version 3.2.3 20030502 (Red Hat Linux 3.2.3-42).
ignoring nonexistent directory "/usr/i386-redhat-linux/include"
#include "..." search starts here:
#include <...> search starts here:
?/usr/local/include
?/usr/lib/gcc-lib/i386-redhat-linux/3.2.3/include
?/usr/include
End of search list.
?as -V -Qy -o /tmp/ccRCof2i.o /tmp/cclLW8Ji.s
GNU assembler version 2.14.90.0.4 (i386-redhat-linux) using BFD version 2.14.90.0.4 20030523
?/usr/lib/gcc-lib/i386-redhat-linux/3.2.3/collect2 --eh-frame-hdr -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 /usr/lib/gcc-lib/i386-redhat-linux/3.2.3/../../../crt1.o /usr/lib/gcc-lib/i386-redhat-linux/3.2.3/../../../crti.o /usr/lib/gcc-lib/i386-redhat-linux/3.2.3/crtbegin.o -L/usr/lib/gcc-lib/i386-redhat-linux/3.2.3 -L/usr/lib/gcc-lib/i386-redhat-linux/3.2.3/../../.. /tmp/ccRCof2i.o -lgcc -lgcc_eh -lc -lgcc -lgcc_eh /usr/lib/gcc-lib/i386-redhat-linux/3.2.3/crtend.o /usr/lib/gcc-lib/i386-redhat-linux/3.2.3/../../../crtn.o
????上面的調用堆棧,充分反應了gcc編譯過程,首先調用ccl執行預處理和編譯,并且在/tmp目錄下生成一個臨時文件/tmp/cclLW8Ji.s文件;接著調用as執行匯編功能,也生成了臨時文件/tmp/ccRCof2i.o;最后執行連接工作。
????如果你只想看gcc的調用堆棧過程而不真正執行編譯工作,怎么辦?用“-###”選項:
??? -###
??? Like -v except the commands are not executed and all command argu-ments are quoted.? This is useful for shell scripts to capture the driver-generated command lines.
????從上面的過程中,我們可以看到,在各個步驟中gcc生成了中間臨時文件,而如果你不想生成這些臨時文件,而取而代之用管道,該怎么辦?用“-pipe”選項:
??? -pipe
??? Use pipes rather than temporary files for communication between the various stages of compilation.? This fails to work on some systems where the assembler is unable to read from a pipe; but the GNU assembler has no trouble.
????舉個例子如下,請看紅色部分的管道:
[root@dbbak tmp]# gcc -### -pipe a.c
Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/3.2.3/specs
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --disable-checking --with-system-zlib --enable-__cxa_atexit --host=i386-redhat-linux
Thread model: posix
gcc version 3.2.3 20030502 (Red Hat Linux 3.2.3-42)
?"/usr/lib/gcc-lib/i386-redhat-linux/3.2.3/cc1" "-lang-c" "-D__GNUC__=3" "-D__GNUC_MINOR__=2" "-D__GNUC_PATCHLEVEL__=3" "-D__GXX_ABI_VERSION=102" "-D__ELF__" "-Dunix" "-D__gnu_linux__" "-Dlinux" "-D__ELF__" "-D__unix__" "-D__gnu_linux__" "-D__linux__" "-D__unix" "-D__linux" "-Asystem=posix" "-D__NO_INLINE__" "-D__STDC_HOSTED__=1" "-Acpu=i386" "-Amachine=i386" "-Di386" "-D__i386" "-D__i386__" "-D__tune_i386__" "a.c" "-quiet" "-dumpbase" "a.c" "-o" "-" |
?"as" "-Qy" "-o" "/tmp/cc8lJo7Z.o" "-"
?"/usr/lib/gcc-lib/i386-redhat-linux/3.2.3/collect2" "--eh-frame-hdr" "-m" "elf_i386" "-dynamic-linker" "/lib/ld-linux.so.2" "/usr/lib/gcc-lib/i386-redhat-linux/3.2.3/../../../crt1.o" "/usr/lib/gcc-lib/i386-redhat-linux/3.2.3/../../../crti.o" "/usr/lib/gcc-lib/i386-redhat-linux/3.2.3/crtbegin.o" "-L/usr/lib/gcc-lib/i386-redhat-linux/3.2.3" "-L/usr/lib/gcc-lib/i386-redhat-linux/3.2.3/../../.." "/tmp/cc8lJo7Z.o" "-lgcc" "-lgcc_eh" "-lc" "-lgcc" "-lgcc_eh" "/usr/lib/gcc-lib/i386-redhat-linux/3.2.3/crtend.o" "/usr/lib/gcc-lib/i386-redhat-linux/3.2.3/../../../crtn.o"
?
??? --help
??? Print (on the standard output) a description of the command line options understood by gcc.? If the -v option is also specified then --help will also be passed on to the various processes invoked by gcc, so that they can display the command line options they accept. If the -W option is also specified then command line options which have no documentation associated with them will also be displayed.
??? --target-help
??? Print (on the standard output) a description of target specific command line options for each tool.
??? --version
??? Display the version number and copyrights of the invoked GCC.
轉載于:https://www.cnblogs.com/ajian005/archive/2012/11/17/2841138.html
總結
以上是生活随笔為你收集整理的linux gcc编译C程序 分享的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Win7 不能安装SQL Server
- 下一篇: MyBatis + MVC 获取 UI