版主
主题
回帖0
积分10609
阅读权限200
注册时间2008-11-22
最后登录1970-1-1
在线时间 小时
|
[介绍] 4 u) [5 l% ?' d$ a
gcc and g++分别是gnu的c & c++编译器 gcc/g++在执行编译工作的时候,总共需要4步 3 E7 Z) @* K) Y$ [
9 ?, s4 m, | `( l ]1 d, l6 `* ~. ~
1.预处理,生成.i的文件[预处理器cpp]
$ a* _7 V: K- L0 l8 v/ a* s5 K2.将预处理后的文件不转换成汇编语言,生成文件.s[编译器egcs]
9 [7 d+ z6 H5 ~& l- Y& Y3.有汇编变为目标代码(机器代码)生成.o的文件[汇编器as]
; j6 b0 t" m- J4.连接目标代码,生成可执行程序[链接器ld]
) a5 E2 h o' ^[参数详解] + `, z/ v% O! }
-x language filename
; }0 O; E7 J0 t' d0 |+ ^0 Z8 I 设定文件所使用的语言,使后缀名无效,对以后的多个有效.也就是根据约定C语言的后 9 L$ c5 d- c2 e5 [9 B3 c
缀名称是.c的,而C++的后缀名是.C或者.cpp,如果你很个性,决定你的C代码文件的后缀 - y4 S/ g! U) D1 R# W
名是.pig 哈哈,那你就要用这个参数,这个参数对他后面的文件名都起作用,除非到了 ; [( B9 T! R1 B( Z8 Q
下一个参数的使用。 0 V. I# [: |+ H6 v/ O/ u
可以使用的参数吗有下面的这些
4 c; C1 M: P# G: U3 J# t J" d `c', `objective-c', `c-header', `c++', `cpp-output', `assembler', and `a
, K; g2 G8 t- l$ Fssembler-with-cpp'.
. i, A3 `" o; ?" P6 b& K8 l% m( r 看到英文,应该可以理解的。 9 H V: q/ Y6 z; l3 B# i
例子用法:
4 h& r: H: F4 {1 M- n gcc -x c hello.pig / o. S L& s0 w. i }# a# ]% @5 \
0 ^+ T) s8 ^# |7 D8 l-x none filename & q0 n4 M6 ]/ N
关掉上一个选项,也就是让gcc根据文件名后缀,自动识别文件类型
V+ D1 ?" O# [ F- `4 N 例子用法: ! N9 x/ u! O% d5 v+ ~
gcc -x c hello.pig -x none hello2.c ( w' ^8 r& H4 q( ?( `
6 M# j: p# N# q, z t% h-c 3 Y4 r/ ?) S; q. S6 L, o3 S
只激活预处理,编译,和汇编,也就是他只把程序做成obj文件
+ x9 P' g* m4 E$ N2 {& i& ` 例子用法:
! q! O) C8 c9 j: v3 l- x. ~ gcc -c hello.c
% s1 \ ?3 v, v- v) N- \+ X2 U+ P 他将生成.o的obj文件 a* p. {4 ?8 J8 f
-S
) i7 ^- P' I" B 只激活预处理和编译,就是指把文件编译成为汇编代码。 ; v/ x8 _& q$ c3 `* Y! V- k
例子用法 * g) |( g7 N9 _; B9 J9 {
gcc -S hello.c 5 _. B, ` R) \
他将生成.s的汇编代码,你可以用文本编辑器察看 . E* {, a% P5 J5 E" z3 H
-E 8 P2 F# V5 w. m, v0 K$ q* n
只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里面.
7 d' L- P: D. W 例子用法:
/ _- F1 g$ p. b/ i- E% Z+ K gcc -E hello.c > pianoapan.txt
7 h1 g8 y6 D% ^ gcc -E hello.c | more # M1 a9 M% C, N6 e4 @
慢慢看吧,一个hello word 也要与处理成800行的代码 6 U# v: w. w+ N8 m1 W
-o : D s D; p0 O6 B# z. i# z( t; F
制定目标名称,缺省的时候,gcc 编译出来的文件是a.out,很难听,如果你和我有同感 1 h# g4 L9 \( s$ V' Z9 B! c
,改掉它,哈哈 9 H) ]6 x$ X& P9 U4 U! S K
例子用法
% Z& ^2 F3 n5 E) m1 \) `! ?* }8 l- M gcc -o hello.exe hello.c (哦,windows用习惯了) / H0 n+ x' i( i1 X } w
gcc -o hello.asm -S hello.c % d+ G. c2 s' Z' x" ?" q
-pipe $ Z( h4 `& s/ d' v' L X, z) q% [
使用管道代替编译中临时文件,在使用非gnu汇编工具的时候,可能有些问题 5 G+ B. _, N2 b9 X
gcc -pipe -o hello.exe hello.c $ M g; ^0 ]4 Z/ n5 \
-ansi
) c9 g ` s6 [1 ^8 B" b5 L* y 关闭gnu c中与ansi c不兼容的特性,激活ansi c的专有特性(包括禁止一些asm inl
& A4 s, L3 b, N! y% ?ine typeof关键字,以及UNIX,vax等预处理宏, ! J) M$ e6 N6 e3 V
-fno-asm 8 J, O/ q) x N6 B
此选项实现ansi选项的功能的一部分,它禁止将asm,inline和typeof用作关键字。
7 a) L% @! |! u& I
2 x. v$ C! S3 T: ?6 ^0 z# w7 m-fno-strict-prototype ; S# Y* K; N9 b! `, I
只对g++起作用,使用这个选项,g++将对不带参数的函数,都认为是没有显式的对参数
0 k5 z6 y B1 R的个数和类型说明,而不是没有参数. 8 G% Q8 H* n& w* m% e) F) Q
而gcc无论是否使用这个参数,都将对没有带参数的函数,认为城没有显式说明的类型
# n, m2 [$ i. O3 F8 W* d- @7 m1 G8 L9 y. c' w# G2 r, b& r
8 c- o- e0 k- T6 G5 O* @( [) A" P
-fthis-is-varialble # |4 O, m$ e7 h6 _' w' K+ v
就是向传统c++看齐,可以使用this当一般变量使用.
U* P1 v9 j% A4 j2 P9 M- W
. n D& X: W+ }* [+ F-fcond-mismatch
/ [0 K1 {( p) v h& ?5 v 允许条件表达式的第二和第三参数类型不匹配,表达式的值将为void类型 6 R* ~ I- j9 W3 t! |
2 E" ^" w$ c: W1 j6 T8 I7 p3 N5 f-funsigned-char 4 W' Y: k; F2 [/ t! [3 V4 p+ k
-fno-signed-char " ]$ ]2 z9 B; y
-fsigned-char
6 u& S! f$ ~9 O/ l1 P, u2 |-fno-unsigned-char
, d( g1 b7 F% g$ D7 ] 这四个参数是对char类型进行设置,决定将char类型设置成unsigned char(前两个参
0 b% v8 ?5 ?7 }, a9 E# Y+ b数)或者 signed char(后两个参数)
" E2 I9 n- `& k& L( S
9 y* N, A8 p0 e8 n" `" v+ k-include file
2 A3 I, Q4 R. w/ h7 H8 @* u 包含某个代码,简单来说,就是便以某个文件,需要另一个文件的时候,就可以用它设
1 D! o! u; m$ _& i0 r' {定,功能就相当于在代码中使用#include<filename>
+ o. T5 [+ w% O8 {/ C 例子用法: 2 `3 F0 z7 f' u8 S
gcc hello.c -include /root/pianopan.h
% f' {. _/ t# M' }2 Q7 K; y D( K; N3 L7 Q
-imacros file
7 s; j7 A& M8 i$ P 将file文件的宏,扩展到gcc/g++的输入文件,宏定义本身并不出现在输入文件中 m, ?! s' P" d* \5 J
) g0 ~& @+ g# |7 o# u& D& K-Dmacro
# I% `4 y- ]- C- F l; O; n; v0 D 相当于C语言中的#define macro
4 l8 C2 Q9 y& f: E; S& ~. O- ~/ @ ) B. ^! r/ _) H9 R/ m4 l9 W% }
-Dmacro=defn
; @2 Z. J1 s# c 相当于C语言中的#define macro=defn
" n3 Q" l- q4 j9 ] + r/ D; P1 @: G! V4 a
-Umacro . z! Y/ h+ k6 E$ l$ a: Q( ^/ v$ u( B# l
相当于C语言中的#undef macro
$ n; w* a B' q4 e0 ~-undef $ d" B, P8 ]( {2 a% w+ Q3 I+ y* }# g5 \
取消对任何非标准宏的定义
1 E0 S, E' a. b1 c( T+ P& n; X9 J$ \ ( F9 m- P1 Z, F+ J" @) a3 J, ?# w
-Idir ! H1 l8 j7 P. D+ O0 I" t; X- x3 g. @) ?
在你是用#include"file"的时候,gcc/g++会先在当前目录查找你所制定的头文件,如
6 X9 G% Q% w: @" q; N果没有找到,他回到缺省的头文件目录找,如果使用-I制定了目录,他 & v& {. F) @ X' T; ?
回先在你所制定的目录查找,然后再按常规的顺序去找.
/ U8 h: c3 O0 ]. r% n! ?. q 对于#include<file>,gcc/g++会到-I制定的目录查找,查找不到,然后将到系统的缺 3 W6 v7 K. \! M Y0 g
省的头文件目录查找 8 d: H8 S- l9 A% \. R; C* ]
% X" t: R0 [* H' v-I-
* t$ ~& s8 Z! w5 f- b* t. C 就是取消前一个参数的功能,所以一般在-Idir之后使用 * o9 \+ K' a/ \0 K* y" K
9 T; H6 {# R- @0 J- d. {0 E2 D-idirafter dir / _/ ^0 F0 L2 R9 `: J6 |
在-I的目录里面查找失败,讲到这个目录里面查找.
" j$ _3 S" m" {# u2 g
1 U% S$ T6 q* M- {-iprefix prefix
{) J4 k& o' G7 a# Z g! R-iwithprefix dir
6 D' ?& ]9 G" S) i1 t, x 一般一起使用,当-I的目录查找失败,会到prefix+dir下查找 % p! Y6 j( E* ^. Z# D0 U
1 |+ K- e) T: w-nostdinc
6 C5 [2 l2 S& A: e% A 使编译器不再系统缺省的头文件目录里面找头文件,一般和-I联合使用,明确限定头 , b+ Z# U) {: M* D' u
文件的位置 2 L! m8 p% w$ \4 B
# |4 W1 S4 n2 O; w& A/ n! w
-nostdin C++ 7 B/ q/ n2 S" R7 j4 ~6 k
规定不在g++指定的标准路经中搜索,但仍在其他路径中搜索,.此选项在创libg++库 }! \1 g" ?1 l" B
使用 ( W M. N1 h: J$ S& P7 q+ J
# y3 |* ]+ I! f( W3 {" A-C . @- d2 m- ]- b0 b, u; b
在预处理的时候,不删除注释信息,一般和-E使用,有时候分析程序,用这个很方便的 6 z; I# K1 {. G1 ~% o9 S6 C" n
) |8 V7 ^: u7 R. C D $ U4 Y: o: p% H' V
-M 7 C$ o: |2 T- Y2 H
生成文件关联的信息。包含目标文件所依赖的所有源代码你可以用gcc -M hello.c % W4 Y1 m/ a( T7 G3 W
来测试一下,很简单。
e" ?* m! h% S : R F* f8 T6 l3 \
-MM 3 K8 \' g( p" } o+ {5 f8 t
和上面的那个一样,但是它将忽略由#include<file>造成的依赖关系。 6 }, {' _! r+ j% x* a, S! P$ v2 @
1 O* C: |6 j4 X1 z6 e1 o
-MD
; Z# o, o; u! i' g, M 和-M相同,但是输出将导入到.d的文件里面 9 a) } w6 o& ^; W5 ^4 r0 v1 J) A
) W; m' m7 {4 O: R( {: @-MMD & B( {! c/ K7 U- Q e4 l6 |1 g4 d3 F
和-MM相同,但是输出将导入到.d的文件里面
. G# ?% S0 M+ f. E2 j: j4 S
2 E2 l4 Z! o% ^# W! N-Wa,option
+ d! |5 W2 Z- p# {7 p/ C 此选项传递option给汇编程序;如果option中间有逗号,就将option分成多个选项,然
! O5 O$ m; J' {) ]! O2 d- {后传递给会汇编程序 Q8 f2 A( u- I9 C5 \! ?7 [& y
6 p5 }/ y$ k* k
-Wl.option
0 @* \7 ?8 ]8 X 此选项传递option给连接程序;如果option中间有逗号,就将option分成多个选项,然
% t5 N7 A+ h9 P( w; i后传递给会连接程序. # ]6 Q6 v9 y+ G) v( b" {
6 b2 `0 r8 C$ e( l9 V% c
-llibrary # h& ^( s( q2 s% D2 p6 {! W
制定编译的时候使用的库
. E' E( |6 l4 T8 f y3 v8 Y 例子用法 , w' E& u& x; b+ C7 t
gcc -lcurses hello.c * k* u7 J* P$ `- K( F
使用ncurses库编译程序 7 E: e, s/ O) d" t K, d8 ]
% r& Q- S0 U, a. U1 c
-Ldir
3 v9 V" n% ?: n3 l5 x 制定编译的时候,搜索库的路径。比如你自己的库,可以用它制定目录,不然
% Q' ~# v; d3 F 编译器将只在标准库的目录找。这个dir就是目录的名称。 " E, ^/ X8 k% C0 [, t+ ~; ?6 j L# L3 T- K
! d5 w+ k; _% E" W* |1 f& t; ]
-O0 * [. ^. [( r1 g; n( y. p; Q7 f
-O1
1 ~! F" }- m# Y-O2
2 U) l/ N# x! a3 ^-O3 6 P8 \* _# t6 c5 l: K5 ~/ s
编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高 . H5 {. S' h4 U, e3 Y, j
) w, t. j" a. G: |-g
: j d: v5 P1 }( p 只是编译器,在编译的时候,产生调试信息。 8 g3 T; i( x6 h# A
, j/ q# ^6 v1 f( i
-gstabs / K9 D8 z6 `: H: e8 p# p* n
此选项以stabs格式声称调试信息,但是不包括gdb调试信息.
6 ?" T1 `( e+ n& x v6 L" x
" u' a8 I% p, C+ l6 i% p! a-gstabs+ & U$ W3 Y6 j1 X* @+ r' [+ F
此选项以stabs格式声称调试信息,并且包含仅供gdb使用的额外调试信息. 9 C# `) n2 c* }" R5 |% T) \2 k
( }2 v6 b. o; U) v' E' `. B* I
-ggdb
' D; O3 E4 Q, B2 M1 a. ~6 C 此选项将尽可能的生成gdb的可以使用的调试信息. 3 f% |: M: R; k) m, Y, j6 z
-static 2 o4 n8 a1 e8 W# f5 k( D/ h! o
此选项将禁止使用动态库,所以,编译出来的东西,一般都很大,也不需要什么
1 G0 u& K5 A9 m. M8 r* @- u$ P动态连接库,就可以运行.
; g, r( K; J: u! ` j. p-share
3 j/ e" ?, o, x0 Z. m 此选项将尽量使用动态库,所以生成文件比较小,但是需要系统由动态库.
# E7 P8 N: g3 {& Z0 I7 O+ X-traditional
. y' Q; N. i% `. X 试图让编译器支持传统的C语言特性
E+ I4 M6 [+ q$ V" @[参考资料]
! w1 d+ t: }. u& h1 x, r5 m( w9 f6 C-Linux/UNIX高级编程
, _% x# H' I" I9 P. o 中科红旗软件技术有限公司编著.清华大学出版社出版 & O0 W, T# M V: W
-Gcc man page 4 G0 ?2 L3 y! N4 |) @& g! p
- ?5 L: Z- e* N# j/ B
[ChangeLog]
! K$ y8 [. @6 I$ V-2002-08-10
" q7 |+ A( U$ `9 \, Y. P$ o% V ver 0.1 发布最初的文档
& w. i, B9 e: O, O0 N+ T! p-2002-08-11 p( ]! j7 S, u/ |/ f
ver 0.11 修改文档格式
2 h i" ?, c w5 K-2002-08-12
: |6 c/ p- F5 o" ? ver 0.12 加入了对静态库,动态库的参数 ' b9 c5 r8 p# t! E0 J
-2002-08-16 " o9 K% L+ V9 @8 N/ a3 p; x$ l& u, O- q! Y
ver 0.16 增加了gcc编译的4个阶段的命令 % s3 ~" x" G) v2 H; c0 f
运行 gcc/egcs ?# w! q( f! p- t2 p$ e& A
**********运行 gcc/egcs*********************** 8 n0 c4 Y2 X3 C; A7 b1 S1 h
GCC 是 GNU 的 C 和 C++ 编译器。实际上,GCC 能够编译三种语言:C、C++ 和 O
+ h* h$ D+ E: m. H, v. L# J8 ybject C(C 语言的一种面向对象扩展)。利用 gcc 命令可同时编译并连接 C 和 C++ ) p" m: w! Y( C) i7 X
源程序。
0 b1 _+ d$ E" Y9 a/ ] 如果你有两个或少数几个 C 源文件,也可以方便地利用 GCC 编译、连接并生成可
& M% q9 p+ }0 u# R% W执行文件。例如,假设你有两个源文件 main.c 和 factorial.c 两个源文件,现在要编
7 F$ ~3 \. h' V$ |5 a. `译生成一个计算阶乘的程序。 " z, k/ a# w g( q3 H( G
代码: & v! y# o3 T, _
-----------------------
* E& @" e/ y% Q清单 factorial.c
2 Z6 |5 ~) i( B7 n I! r' V. W-----------------------
5 R- d5 K0 J+ M/ P7 Pint factorial (int n)
5 o' q+ W1 f E' Z% `{
& v/ w( L5 h, c R if (n <= 1) , O9 X3 l7 _) Y3 q
return 1; & ?0 t4 M. e. H: F: G: H- p
else
" q( B! b! A6 |5 g) j3 z5 T3 _ return factorial (n - 1) * n; 6 i. ?: @) N5 U+ Z* V
}
5 u( t4 G# W5 T7 a, v4 m& Y-----------------------
8 T3 B! ^) C. j" w5 J/ ~0 ?' H% r清单 main.c 4 p0 T' t! }. V
----------------------- ( Z* y9 a+ K3 A. d d6 ]. }
#include <stdio.h>
) a H1 f: ~9 t' {- `#include <unistd.h>
2 k& o/ j# p6 ^6 Sint factorial (int n); ; ^4 u& _, I: T2 W1 t, W
int main (int argc, char **argv) 8 w+ B9 G3 m# w# l% S5 q- z9 D
{ 9 e I5 v, X% `" ~
int n; * Q; m, b! s b
if (argc < 2) & I0 M8 o, j* U4 F- ~
{ ' I5 `: T8 V# y# I% C0 d" g
printf ("Usage: %s n\n", argv [0]); _; f3 v k& f0 c* [
return -1; 1 o! ^ f. A7 r7 R# u* [, A9 Y( C
} % M" G' K5 i2 e
else
U5 _5 }( F5 Z! S {
" i3 M8 o0 x& j% ?- v# \; _" i n = atoi (argv[1]);
& {/ q3 I: C/ _5 P printf ("Factorial of %d is %d.\n", n, factorial (n)); 8 L: l' g- C+ V7 M' y
}
" o' n2 L2 F2 N) x return 0; " ]' N3 t7 H! k. M
}
4 g- G6 B. U ~4 k& G----------------------- % w$ l3 ?3 v" d5 \/ k
利用如下的命令可编译生成可执行文件,并执行程序:
2 ?0 t1 N6 ~3 t$ i& w2 h$ gcc -o factorial main.c factorial.c
8 V7 w& `% A. l3 ?- u0 x$ ./factorial 5 ! O# @3 U( A# M" B; E, x% {
Factorial of 5 is 120. ( d; p( @6 C6 F( Q C# G4 ^
GCC 可同时用来编译 C 程序和 C++ 程序。一般来说,C 编译器通过源文件的后缀 ) D' ^, Z; z$ i* U1 E0 c2 c2 o
名来判断是 C 程序还是 C++ 程序。在 Linux 中,C 源文件的后缀名为 .c,而 C++ 源 / u$ `/ I/ f) V% n, t
文件的后缀名为 .C 或 .cpp。但是,gcc 命令只能编译 C++ 源文件,而不能自动和 C
4 Q: H+ f3 p4 c7 `++ 程序使用的库连接。因此,通常使用 g++ 命令来完成 C++ 程序的编译和连接,该程 3 i$ p" E) G. s8 p+ x+ {5 v
序会自动调用 gcc 实现编译。假设我们有一个如下的 C++ 源文件(hello.C):
" W& u4 Y$ _, ~- A$ `$ B#include <iostream>
7 e( ]- h8 j4 t7 s+ ?* _; kvoid main (void)
( ?# M* Z) L; z: R# L{
, g, f9 w% I. Y0 F cout << "Hello, world!" << endl;
5 o u" H, ?/ Y} . L- J* c# s G4 T
则可以如下调用 g++ 命令编译、连接并生成可执行文件:
- T) @$ B/ O% U# r$ g++ -o hello hello.C
; C& N0 g6 _; O1 N/ i2 ?$ p. G" i$ ./hello
: }! z+ s9 N" v" t6 o/ jHello, world! 8 O1 _+ h6 h7 h2 W8 O$ m
**********************gcc/egcs 的主要选项********* 9 w4 `# n+ j% B2 W( s
gcc 命令的常用选项
: \8 ?( B6 c8 X! N; s# i- f8 i选项 解释 # ~7 S T6 j7 D" F* Q) ^
-ansi 只支持 ANSI 标准的 C 语法。这一选项将禁止 GNU C 的某些特色, 7 M" d8 K% b( {# \# ?! @! D0 Z
例如 asm 或 typeof 关键词。
/ j, x1 y2 a9 o/ @, h" T; b-c 只编译并生成目标文件。
4 f( p k' n' s* N& C7 k-DMACRO 以字符串“1”定义 MACRO 宏。 3 Q1 N- j: x! O1 [" g" R
-DMACRO=DEFN 以字符串“DEFN”定义 MACRO 宏。 " F- E2 K+ f0 k; u- X
-E 只运行 C 预编译器。 ( z9 z# S0 [2 p9 ?7 K: f
-g 生成调试信息。GNU 调试器可利用该信息。
- k* j: \! V( M0 }: Y, C-IDIRECTORY 指定额外的头文件搜索路径DIRECTORY。
. T& E7 k# E2 q+ }, C6 j-LDIRECTORY 指定额外的函数库搜索路径DIRECTORY。
5 b' @0 x. L( M. f" q0 C-lLIBRARY 连接时搜索指定的函数库LIBRARY。
& ~7 w; K b/ }* y-m486 针对 486 进行代码优化。
/ t/ W. ^7 l8 C6 {8 V9 r0 `-o FILE 生成指定的输出文件。用在生成可执行文件时。
7 D9 t+ L, }- w$ x c) q-O0 不进行优化处理。
5 x2 q6 w |* u& ?; H-O 或 -O1 优化生成代码。
! a# n& a5 c5 X6 A- g% ]" Y-O2 进一步优化。 , C- V3 `0 Q. S& ?
-O3 比 -O2 更进一步优化,包括 inline 函数。 " d* @) a& u# w9 T% N
-shared 生成共享目标文件。通常用在建立共享库时。 8 l) p- k3 `% o# u- U) \; A7 q
-static 禁止使用共享连接。
3 Q( B2 q5 o. V& b9 s$ ~* R-UMACRO 取消对 MACRO 宏的定义。
, C3 O7 G5 g. m g! Q-w 不生成任何警告信息。 ( B+ [; _( u7 @
-Wall 生成所有警告信息。
4 `, ~* s. `3 [ |
|