版主
主题
回帖0
积分10609
阅读权限200
注册时间2008-11-22
最后登录1970-1-1
在线时间 小时
|
[介绍]
2 O- s' _; _3 C. m! f, `gcc and g++分别是gnu的c & c++编译器 gcc/g++在执行编译工作的时候,总共需要4步 S. s. ?" C8 Z- C4 E/ W) J8 z
1 n- z9 _" |$ K* ^+ U1 B1.预处理,生成.i的文件[预处理器cpp] `3 F7 p2 a& W+ Z
2.将预处理后的文件不转换成汇编语言,生成文件.s[编译器egcs] - _4 [/ e2 U! r; N* I
3.有汇编变为目标代码(机器代码)生成.o的文件[汇编器as] - f! W6 z: P, g
4.连接目标代码,生成可执行程序[链接器ld] 5 H, Q: P+ m+ F7 M/ o) m: Z
[参数详解] 5 r6 s$ w# k) `7 O) [
-x language filename
6 g( H( z; b4 `" r' l 设定文件所使用的语言,使后缀名无效,对以后的多个有效.也就是根据约定C语言的后
7 e/ d4 K+ }9 ?7 C缀名称是.c的,而C++的后缀名是.C或者.cpp,如果你很个性,决定你的C代码文件的后缀
/ k0 l: q/ E, H5 ]$ a名是.pig 哈哈,那你就要用这个参数,这个参数对他后面的文件名都起作用,除非到了
. o$ a" [9 d* L: z4 S下一个参数的使用。 ?; |2 P$ v" K7 v
可以使用的参数吗有下面的这些 8 w w5 g5 \3 O+ a9 W
`c', `objective-c', `c-header', `c++', `cpp-output', `assembler', and `a : }0 {, V7 @1 b/ S! U3 G, Y8 C! j
ssembler-with-cpp'.
1 H2 x+ P8 W4 L/ N 看到英文,应该可以理解的。 ! `9 F z. ^% w3 e4 U0 E& g
例子用法:
+ ^! G4 M; t8 R3 |" x gcc -x c hello.pig ) O+ h- Z- u# }+ g
! p& @$ s- E# k& w) a-x none filename
' @( d U. r- o 关掉上一个选项,也就是让gcc根据文件名后缀,自动识别文件类型
2 X% r( `& N1 {( O8 V5 I3 x$ T5 j* R 例子用法:
& Q5 u8 F: \+ J/ G gcc -x c hello.pig -x none hello2.c ' b/ `4 D! A$ ]4 J: R
/ ~! W R" i8 G4 ]-c # t# _& J& D/ _. ~$ R: `( @
只激活预处理,编译,和汇编,也就是他只把程序做成obj文件 7 r" _; |' K( ]7 R: G+ m7 F
例子用法: ) M' s0 a' V. N6 T r
gcc -c hello.c 9 S: Q( u" U- [- p7 I) E. y8 w# y0 t
他将生成.o的obj文件 - ~; m6 M# m4 k1 S
-S 9 w: _. x* T1 \! M
只激活预处理和编译,就是指把文件编译成为汇编代码。
1 B, r& e8 W+ Z/ Z' ]0 C9 X 例子用法 S/ W3 l9 b4 c+ X) @+ b2 o
gcc -S hello.c - S) ?& y: z/ r& I; a4 Z" Y+ e. H
他将生成.s的汇编代码,你可以用文本编辑器察看
6 j; ]+ V6 i- D4 [5 ?-E % M( [% z |; G
只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里面.
: `: J! Y& ?, j# ~5 P- Y 例子用法: $ I: l' K; O2 y3 k, Q
gcc -E hello.c > pianoapan.txt . q" g% d9 i$ b( M+ A: A/ s# ?
gcc -E hello.c | more
5 R. t& ]5 _8 A/ l' X1 x 慢慢看吧,一个hello word 也要与处理成800行的代码 + _2 t8 }- q) E j7 e8 ~
-o
9 R! @9 H; X7 C$ w 制定目标名称,缺省的时候,gcc 编译出来的文件是a.out,很难听,如果你和我有同感
3 J: @ E, o' U) ?2 @) D0 j1 ~: M7 ?,改掉它,哈哈
) M- E# M7 d2 E 例子用法 5 |* R$ ]5 x4 ~% G8 M2 n: e5 Q3 \
gcc -o hello.exe hello.c (哦,windows用习惯了)
7 @, W, L/ z/ p, X' J- W gcc -o hello.asm -S hello.c
- d4 a, C. H( J* ]+ Q1 X( ^) G-pipe & W, g2 K% p# T& g; }
使用管道代替编译中临时文件,在使用非gnu汇编工具的时候,可能有些问题 ) D2 Z8 x+ F N1 f/ z7 X
gcc -pipe -o hello.exe hello.c , v4 k3 `7 Z' {, r" p
-ansi
/ u- s2 {$ e5 C+ ?" l) R 关闭gnu c中与ansi c不兼容的特性,激活ansi c的专有特性(包括禁止一些asm inl
$ Q* V# j& L/ a( n. V/ ?! H* Kine typeof关键字,以及UNIX,vax等预处理宏, ( [. H1 \1 j0 O( v
-fno-asm * H. X6 c# q: j/ Z- ]& o8 J
此选项实现ansi选项的功能的一部分,它禁止将asm,inline和typeof用作关键字。
$ G' ?# X' M0 g2 `2 p
9 U' P" m+ G* ~9 _1 R8 t-fno-strict-prototype
2 ]. z, x2 |5 D 只对g++起作用,使用这个选项,g++将对不带参数的函数,都认为是没有显式的对参数 # } w- U, w% x) G7 G/ g$ M, _) |' b
的个数和类型说明,而不是没有参数.
: l# }! S: S: I S 而gcc无论是否使用这个参数,都将对没有带参数的函数,认为城没有显式说明的类型 * C( \% F( D' H/ C/ {
2 c/ w- `( m0 H8 P4 m0 U: L
/ H: G+ C0 y9 a% |$ S-fthis-is-varialble " K& _0 x9 h& K9 J6 ?) _, M
就是向传统c++看齐,可以使用this当一般变量使用. 5 x; h- J: @* b6 R' P
) _& L! P0 l) ^" {! I* ~2 O
-fcond-mismatch 8 E K- B0 b9 j6 X$ p
允许条件表达式的第二和第三参数类型不匹配,表达式的值将为void类型
% x# X7 {% w9 m8 W. q' t
* }, C9 R( ]: v) U/ q5 I# X-funsigned-char
% `5 F; {* T# H/ @-fno-signed-char
9 R$ o# i. A1 G9 r8 d" c/ D$ c3 p! q-fsigned-char 1 O( Y4 ]( j9 a+ d( V$ I
-fno-unsigned-char
' n2 |3 N* @. m0 Q9 u v 这四个参数是对char类型进行设置,决定将char类型设置成unsigned char(前两个参 ! }4 m. }8 J0 z6 q% b
数)或者 signed char(后两个参数)
* F8 [" x: A/ _' u6 s% {; f " h9 t( t* E! z& c$ f
-include file 4 |" _, i5 \: P. s; s! x
包含某个代码,简单来说,就是便以某个文件,需要另一个文件的时候,就可以用它设
, ]- @6 f; B* H* p定,功能就相当于在代码中使用#include<filename>
' ~0 ], K: F; @- k( ] 例子用法: # E& U( S! [, J* N
gcc hello.c -include /root/pianopan.h % h. F, A# ~9 z. R
3 w5 E3 d& k( m2 _' c-imacros file
' a9 y7 R+ n4 [7 x0 C) F# Z/ E 将file文件的宏,扩展到gcc/g++的输入文件,宏定义本身并不出现在输入文件中
& b. O4 _7 |6 ]) J% p. `
& [2 b) _- t* K' m% I- I-Dmacro 9 }' }( q2 N7 W$ r+ F( {! n( c
相当于C语言中的#define macro
- w! _( B8 q% w) O4 Q, g1 u
6 m/ n( {" X0 {-Dmacro=defn ( J8 B4 r3 n7 }7 f7 n! n2 }/ y
相当于C语言中的#define macro=defn ! U% Q1 b, Z% ?
) B7 |2 N x" z: F( U4 T
-Umacro c/ P: @6 W9 F& y3 W, @; E
相当于C语言中的#undef macro 9 [; [6 N. ]1 G C, U
-undef " i* z/ D. x1 o1 A; g w
取消对任何非标准宏的定义 " P6 [9 J4 D9 w% ?: {- B$ g
' e1 V' E3 H& {. ^; |) ?/ O' O. C) K
-Idir
1 j! [9 O2 \0 h/ e" R3 A$ D! I7 _ 在你是用#include"file"的时候,gcc/g++会先在当前目录查找你所制定的头文件,如 * _: {$ J6 B" w& E! H2 }1 ]
果没有找到,他回到缺省的头文件目录找,如果使用-I制定了目录,他
* K& ^! v% x6 N/ U& S; B 回先在你所制定的目录查找,然后再按常规的顺序去找. r$ w9 Q) O: C" ?
对于#include<file>,gcc/g++会到-I制定的目录查找,查找不到,然后将到系统的缺
4 C* v! `* s3 q5 C s2 n3 u/ E省的头文件目录查找
% Q5 Y3 v. m9 M5 p
7 S, i4 T" }# d# g-I- - S% a. q/ M; W4 u0 W: \4 |
就是取消前一个参数的功能,所以一般在-Idir之后使用 : R) B9 p: j" o& A
' ^/ h) G: a+ V) t d* b-idirafter dir
6 j$ \% ?: v4 R( X" G: ~8 q 在-I的目录里面查找失败,讲到这个目录里面查找.
+ J" D% R+ k. W/ o0 f 0 t7 @) L4 q; J% X7 C# C x
-iprefix prefix $ q# B0 P! @+ @/ y/ x1 P# _( X# x
-iwithprefix dir
7 V! h1 s4 ^# ?3 S 一般一起使用,当-I的目录查找失败,会到prefix+dir下查找
. ^: g- L8 C. P2 B* N0 c- ^2 Z" T
) t8 `- e3 t9 y$ M-nostdinc 5 a% v# k) i. [8 C
使编译器不再系统缺省的头文件目录里面找头文件,一般和-I联合使用,明确限定头
* q' o) E" p- g文件的位置 1 ]( c/ J* f5 V, f
1 U3 ?8 w$ S4 [& w7 |& ?& }6 V
-nostdin C++ 1 a5 O$ J! ^: l
规定不在g++指定的标准路经中搜索,但仍在其他路径中搜索,.此选项在创libg++库
, k' j1 C& B7 ~2 T3 Z2 j! B6 @使用
7 N6 _1 q' l! d( A, A
- y+ z# H9 x5 a-C
, E3 J& J) i1 H+ |3 g3 t- h 在预处理的时候,不删除注释信息,一般和-E使用,有时候分析程序,用这个很方便的 % s/ o" _) X1 S% x: ^
0 p2 E$ J N \+ {
J2 Y6 v% h4 G- z-M 6 A0 N! I5 w& x" o7 M" {6 }: |
生成文件关联的信息。包含目标文件所依赖的所有源代码你可以用gcc -M hello.c
! z3 u+ l8 y! Y* a" [来测试一下,很简单。
P' o6 a1 D" e" e+ O ! b8 L6 `# P- F) g1 T( V* [
-MM ) c% J" s+ X; h
和上面的那个一样,但是它将忽略由#include<file>造成的依赖关系。 * J# D8 W1 @" s
5 V4 K6 }" U7 g6 g! V/ l: v. o) ^0 o, ~-MD : t- O3 H1 w& o. I1 {/ J
和-M相同,但是输出将导入到.d的文件里面
* S* i L$ t- X% A9 j # s& H5 @" T! B6 c1 H8 |. r9 I
-MMD
2 D/ B3 o5 x9 M 和-MM相同,但是输出将导入到.d的文件里面 & R# T5 p! v9 x
7 Q1 r" M4 X2 Z4 L6 Q-Wa,option $ u! m- B D, S# g. J
此选项传递option给汇编程序;如果option中间有逗号,就将option分成多个选项,然
- M* D8 B( R7 T0 Z! E. j) F/ r' A后传递给会汇编程序 7 L! \( {# M* }* l0 @& J
% V" [* r% {4 N; K& F- V7 y
-Wl.option
! @# K4 Q( W* k7 R" S/ O g 此选项传递option给连接程序;如果option中间有逗号,就将option分成多个选项,然
. U7 r% V$ {) @4 E/ k8 ^; p+ V后传递给会连接程序. + S( \8 ]4 r( c7 E/ X' q) c3 b
3 P- D* m5 a" x$ D* A-llibrary ' Z) }$ q" |8 T2 B! S
制定编译的时候使用的库 1 }% Q0 Z7 p; T/ A; d1 F
例子用法 7 L3 W3 t( z' A( ]
gcc -lcurses hello.c
D" ]' C: W n7 z: W 使用ncurses库编译程序 - K# F* `: ~" P# |; W" X. g8 `
( q' D3 V2 M3 S5 p0 _5 @3 g, o-Ldir % t: u* n$ [4 z( K. u
制定编译的时候,搜索库的路径。比如你自己的库,可以用它制定目录,不然 8 R; H7 w# i7 `- _
编译器将只在标准库的目录找。这个dir就是目录的名称。 8 u6 ~8 ^9 w5 @* x- r/ D; n% ^9 Y
! P; L6 A" ^0 J8 d2 S
-O0
3 n- I' m' D+ P" j# [" ~, t, w& O-O1 8 H4 K3 n" N* _8 `
-O2
& |( N; |& [5 {5 t5 N, { K-O3 ( S2 W8 _3 S& R* g
编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高 : c3 O, ?1 W7 I( m$ |! R/ \' J
) a, a) S9 y0 B% o7 y8 e, C- ~4 k# V
-g
7 I* S3 K$ h. V& x 只是编译器,在编译的时候,产生调试信息。 % o; n! y& R* X2 P
}& S3 e! U3 F% w2 u-gstabs
3 K" m1 v8 v. P: D 此选项以stabs格式声称调试信息,但是不包括gdb调试信息.
# E1 r e% i, K& k6 ]6 F& q 2 r; ]. {% T8 a/ W$ t
-gstabs+ - N9 s5 Z) B5 A7 F3 S8 w
此选项以stabs格式声称调试信息,并且包含仅供gdb使用的额外调试信息. # e3 Y* X. z( O# q3 Q( I2 R
+ B1 A$ z/ _4 v8 O5 d X9 B
-ggdb ( B- I! t- B) |* y, Y8 H
此选项将尽可能的生成gdb的可以使用的调试信息. 7 s' y9 n) s. w+ r2 k2 K1 k
-static 0 L/ n5 v, c2 E& C
此选项将禁止使用动态库,所以,编译出来的东西,一般都很大,也不需要什么
8 R) U; b2 U4 S9 n/ ?动态连接库,就可以运行. ! y9 U1 {7 F/ U
-share 3 w) ^/ ]$ I- |- y0 `
此选项将尽量使用动态库,所以生成文件比较小,但是需要系统由动态库.
4 b" C: g! W1 B# G6 ~+ e/ \-traditional , G/ x+ ^3 A1 W: a/ B0 Q9 k
试图让编译器支持传统的C语言特性 $ w$ G4 Y: k: d7 _$ M8 O3 D
[参考资料]
: F5 \3 `4 B, @) U! l w-Linux/UNIX高级编程 * a& A/ W, D' t. S& L' y' }3 O0 F
中科红旗软件技术有限公司编著.清华大学出版社出版
5 d" @2 [; y8 r$ i-Gcc man page
. I2 w) G+ c& h1 [; ] % U: ?2 }3 [1 G# e, F
[ChangeLog]
5 o5 Z2 V1 u* `-2002-08-10 ) p5 C/ @" H- B5 ^6 W* ^3 e
ver 0.1 发布最初的文档 ' V( g# e8 |9 O8 r* k8 }
-2002-08-11
& m9 v& d3 E) q* b; X7 o ver 0.11 修改文档格式
/ E& P. J `9 F5 Y) ~" `-2002-08-12
4 D) i |- G# h* h7 R, ?3 J) N ver 0.12 加入了对静态库,动态库的参数
$ Q1 f3 [1 V3 n/ g i; W9 P9 @" ~-2002-08-16 6 \, {2 A; o p' y/ Q* v1 I; V# h
ver 0.16 增加了gcc编译的4个阶段的命令
# w) n) J, o, h" B9 h运行 gcc/egcs 3 V1 R2 D2 h |4 H8 z
**********运行 gcc/egcs*********************** - J: P- R, l+ h) ^6 X
GCC 是 GNU 的 C 和 C++ 编译器。实际上,GCC 能够编译三种语言:C、C++ 和 O
' R- A5 O: M( b. Lbject C(C 语言的一种面向对象扩展)。利用 gcc 命令可同时编译并连接 C 和 C++
+ U7 `; }( B5 c源程序。
' N1 }" q* V9 P# ~5 ?) Z3 Y 如果你有两个或少数几个 C 源文件,也可以方便地利用 GCC 编译、连接并生成可
' d+ a5 |! X# o0 C8 Z9 D执行文件。例如,假设你有两个源文件 main.c 和 factorial.c 两个源文件,现在要编 6 o" C* \ Y6 b/ o) [- ]! B
译生成一个计算阶乘的程序。 2 s% p' f. v w; }2 L
代码: % K/ j- e3 | s& E M9 X# Q. f
----------------------- " s- P1 `$ `( b9 a9 d/ n0 l6 C
清单 factorial.c
8 k: D/ Q/ ~* ?! Z----------------------- 9 J8 r3 \; m. w/ G, r8 e3 o$ H$ @( g
int factorial (int n) " A5 k6 s5 O9 q8 G! G. g5 w+ C& I
{
" e$ H/ I) G! r, h if (n <= 1)
+ d9 E3 K+ N) F ~! B return 1;
* Q; y, u3 p# X; a else
- x& P9 ]* k$ D3 `& J4 P$ B: Z5 B return factorial (n - 1) * n;
, r. `& r9 M6 u6 u} ; j( K1 W2 |4 e! t. }, [9 y
-----------------------
- u$ W5 k2 U) F6 z清单 main.c
7 S+ H4 ^, ]( R9 }5 v! y----------------------- ( W v5 `3 O {' A* B" s
#include <stdio.h> % {+ F$ U! @3 U2 N9 M" [
#include <unistd.h> % ?0 @, }/ `# O/ i" Z& p* E* z6 t
int factorial (int n);
9 O ~. \( a( J: A' Dint main (int argc, char **argv)
( o: i: o# m8 H* r6 \. R( c/ V7 u{
" f: D5 I' g" z# i int n;
# |: b- ^: |+ g8 s' C4 f if (argc < 2) + c( e, s1 w7 t, p% L$ X
{
# l/ ?, \& z6 ]3 Z printf ("Usage: %s n\n", argv [0]);
7 F/ ] t5 w5 j, ~ return -1;
# R: H* |% z3 q# E( e }
! ^: Y' d2 L/ o6 C5 k# b9 p else
4 ^3 `5 h9 N/ Z( O* `* p { ) O; s, R' ]6 j9 L% T9 K% O& \1 n
n = atoi (argv[1]);
" i, z8 G; ]' V0 E! x printf ("Factorial of %d is %d.\n", n, factorial (n));
) \ D3 {7 D1 m9 t1 X9 j# K }
% P2 O1 a, h6 V/ Z F return 0; j/ \% u: l. d! d
} 9 {6 O' ~ C/ A a
----------------------- - D" ~( H2 |3 s1 d' ~3 f T7 E
利用如下的命令可编译生成可执行文件,并执行程序:
7 \4 y2 {; S0 k5 c' i$ E+ y6 @$ `$ gcc -o factorial main.c factorial.c $ ~0 N8 P. b, p# c( E
$ ./factorial 5
x7 E; c& S! I4 dFactorial of 5 is 120.
2 y9 t4 {! o# u GCC 可同时用来编译 C 程序和 C++ 程序。一般来说,C 编译器通过源文件的后缀
" O+ m& c! c2 Q- [. m% T& C名来判断是 C 程序还是 C++ 程序。在 Linux 中,C 源文件的后缀名为 .c,而 C++ 源 , N" S( U4 r5 b6 u
文件的后缀名为 .C 或 .cpp。但是,gcc 命令只能编译 C++ 源文件,而不能自动和 C
8 I/ R9 P4 I7 O( q( |7 @: a2 E$ T/ [2 {8 {++ 程序使用的库连接。因此,通常使用 g++ 命令来完成 C++ 程序的编译和连接,该程
& R* `4 G& T- y" O! y/ b序会自动调用 gcc 实现编译。假设我们有一个如下的 C++ 源文件(hello.C):
7 ^- l: m/ h6 \' N#include <iostream> + E8 G* U8 V/ y2 z: A2 J
void main (void)
& v8 _: F/ b- v2 N8 @5 f{ 5 \' @% f% A9 w( I, a6 \2 G2 k2 z
cout << "Hello, world!" << endl; 9 \& F6 H% ^% N& S% h
} 1 g1 \: w4 ~) T; l/ M
则可以如下调用 g++ 命令编译、连接并生成可执行文件:
/ J# \- `( B- l7 }5 T$ g++ -o hello hello.C
# p1 j# }8 v/ U# C, Z& K4 e* {! H$ ./hello
+ D" ]0 ~" _; ~! l- i; [Hello, world! / V% }' \8 o- v# k% t: w
**********************gcc/egcs 的主要选项********* 9 I/ i3 E" m* I
gcc 命令的常用选项 & r# o' |" ]' t, d% a1 X5 n
选项 解释 ' m4 W4 E3 w; K! @6 _
-ansi 只支持 ANSI 标准的 C 语法。这一选项将禁止 GNU C 的某些特色, + G1 K% ?; R4 h- D+ a# P
例如 asm 或 typeof 关键词。
1 e! M0 ~( N8 L) }$ C-c 只编译并生成目标文件。
) W5 c2 Z7 [/ v- F-DMACRO 以字符串“1”定义 MACRO 宏。
& a" Q6 L+ Z. F+ F, M$ C, A-DMACRO=DEFN 以字符串“DEFN”定义 MACRO 宏。
' Y# G% r' y5 Q3 R9 ?" F-E 只运行 C 预编译器。
! n" Q$ H8 A8 s/ `% W8 r0 S-g 生成调试信息。GNU 调试器可利用该信息。
8 k. U) I$ h, R& K0 i; E-IDIRECTORY 指定额外的头文件搜索路径DIRECTORY。 ) g7 \5 r3 |5 }- N( `7 g% P
-LDIRECTORY 指定额外的函数库搜索路径DIRECTORY。 ' f+ |, U A/ i# ]5 l
-lLIBRARY 连接时搜索指定的函数库LIBRARY。 3 _7 w6 O) ^6 g) N+ `
-m486 针对 486 进行代码优化。 # }. ~; a C! D
-o FILE 生成指定的输出文件。用在生成可执行文件时。 5 o m: A& Y. G3 ^% x. g d
-O0 不进行优化处理。 ; @6 }: l$ s; k" k6 |9 f2 L
-O 或 -O1 优化生成代码。 ! @" K" ~0 {% `
-O2 进一步优化。
( L. ?( f# I- e3 j, a-O3 比 -O2 更进一步优化,包括 inline 函数。 6 o, Y/ \* h/ g
-shared 生成共享目标文件。通常用在建立共享库时。
6 ?! _6 v! x+ _/ Q+ [: K/ a-static 禁止使用共享连接。 7 V2 e5 {# n# |# O
-UMACRO 取消对 MACRO 宏的定义。 ( x# E1 N# ]9 Z2 I5 }5 c
-w 不生成任何警告信息。 % w1 q( y4 b& q: N x/ f8 m1 E. p s
-Wall 生成所有警告信息。2 |+ }7 m5 W- s+ w: T
|
|