版主
主题
回帖0
积分10609
阅读权限200
注册时间2008-11-22
最后登录1970-1-1
在线时间 小时
|
[介绍]
; S* O- c3 z% Z0 b. Ogcc and g++分别是gnu的c & c++编译器 gcc/g++在执行编译工作的时候,总共需要4步 6 T) l5 \2 e# X5 k6 o
4 W, Z3 L2 E. u8 Q! x, }
1.预处理,生成.i的文件[预处理器cpp] 9 v x5 K( ~. Y u
2.将预处理后的文件不转换成汇编语言,生成文件.s[编译器egcs] : p/ _ p2 c$ X p% g/ W
3.有汇编变为目标代码(机器代码)生成.o的文件[汇编器as]
; v$ b; J* w# k( Q6 }- a4.连接目标代码,生成可执行程序[链接器ld]
2 O7 H9 {9 W+ r0 b& h% k% F[参数详解] 7 w6 Z$ p# R7 I. w1 D5 u
-x language filename
* V) `2 }/ N# G3 n8 ~" F, A 设定文件所使用的语言,使后缀名无效,对以后的多个有效.也就是根据约定C语言的后
1 q. X! E/ }. ?7 N" f, Z缀名称是.c的,而C++的后缀名是.C或者.cpp,如果你很个性,决定你的C代码文件的后缀
* o+ E+ R/ v0 o/ A# }名是.pig 哈哈,那你就要用这个参数,这个参数对他后面的文件名都起作用,除非到了
. ]' {# ~0 I# ]* K6 D# u下一个参数的使用。 8 N0 o) ~% n7 R F; P h
可以使用的参数吗有下面的这些 + c5 c# I) e# @) [; x. G& I
`c', `objective-c', `c-header', `c++', `cpp-output', `assembler', and `a
. T2 P3 S* B+ Z! q+ A2 Q9 ^ssembler-with-cpp'. , Q0 m. Z# v/ v8 O$ C) O
看到英文,应该可以理解的。
+ b, b! X. w' d* B" N 例子用法: % D7 v5 s5 ~7 Y. a" \% m
gcc -x c hello.pig
3 b$ z: X+ W( g& L5 g& a; F . V5 r: o0 f- q$ z4 l% H r3 I9 {3 _
-x none filename 3 d0 o' J. ?8 Q. R% e6 _" J* N" q4 S
关掉上一个选项,也就是让gcc根据文件名后缀,自动识别文件类型 2 K# u6 h5 ?! t9 G" `8 l0 w
例子用法:
3 D- q" T% h3 Y gcc -x c hello.pig -x none hello2.c + J; x8 b9 ^! x% Q
9 D9 V: J& S! Y$ E9 v+ U6 l y-c ( t' C e5 h8 D3 a+ h& Y L& B
只激活预处理,编译,和汇编,也就是他只把程序做成obj文件 0 m( |5 G$ T" L! ]/ B
例子用法:
% N, } Z3 W' i6 O3 m gcc -c hello.c
a# R- t6 M! x% ^0 |3 P 他将生成.o的obj文件
9 t, U- y2 @2 o2 Z-S
" c! y, E! ] M! f+ F/ ? 只激活预处理和编译,就是指把文件编译成为汇编代码。
! i g: B- b7 o0 X. C 例子用法
3 {6 ]5 @, d9 F gcc -S hello.c ! _9 ?& X) i, Q* {/ G( w
他将生成.s的汇编代码,你可以用文本编辑器察看
: g- ^1 A" Y v. F" D- m6 Q6 }-E
" I. ]( i! K& T& S0 T8 m; j 只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里面.
! U. H9 L3 {+ C, ^3 V, U# v9 f! E 例子用法:
( o3 f$ _& _3 ~ M4 W: E' R gcc -E hello.c > pianoapan.txt
, S7 C$ e* r/ c# a! W* x gcc -E hello.c | more 2 I' o- P4 T8 b
慢慢看吧,一个hello word 也要与处理成800行的代码 ! Z$ }. \- ~( x" w& o1 d2 P: _" E
-o
4 i! j( k( v0 W; ]3 W 制定目标名称,缺省的时候,gcc 编译出来的文件是a.out,很难听,如果你和我有同感
1 Q/ [& I, ^7 P+ ]0 s,改掉它,哈哈 3 e; N( S& u- E; _$ A
例子用法
$ Z! ~: [. n: J' O1 J gcc -o hello.exe hello.c (哦,windows用习惯了) : L. H0 {8 n2 g4 R+ ?% ^- E
gcc -o hello.asm -S hello.c 0 `; I+ k; Z8 D! \. i- k! }
-pipe 3 \- U4 p3 V/ i' x" U
使用管道代替编译中临时文件,在使用非gnu汇编工具的时候,可能有些问题
( {+ Q2 ^( ]0 |- [ gcc -pipe -o hello.exe hello.c ( Q" ?, u2 f3 x+ J+ a3 j
-ansi
7 L; f- w* {$ x' i3 L1 }9 R 关闭gnu c中与ansi c不兼容的特性,激活ansi c的专有特性(包括禁止一些asm inl % t& Y p# l$ H" {, l
ine typeof关键字,以及UNIX,vax等预处理宏, 7 q4 p' P' N/ [+ Y. d0 `
-fno-asm
+ p" B; k8 p9 _0 _4 S2 C* c 此选项实现ansi选项的功能的一部分,它禁止将asm,inline和typeof用作关键字。
1 G2 |1 O( }1 y: _7 r# Q
4 i1 c+ q( W5 @6 S' g- c4 B/ K0 { L, p( ]-fno-strict-prototype e x }, J y1 w( l* ?
只对g++起作用,使用这个选项,g++将对不带参数的函数,都认为是没有显式的对参数 # G% i" K& |$ r q! z
的个数和类型说明,而不是没有参数.
% d" E4 c: J: N! f, k. W) g 而gcc无论是否使用这个参数,都将对没有带参数的函数,认为城没有显式说明的类型
9 l4 T4 C- |4 a+ D1 l. k0 P$ o# f Q5 q0 P/ b& S) M* }+ k% K
4 X: @% K* x5 c# z) X-fthis-is-varialble
* y% [( x: @/ q4 ?; B) a6 G 就是向传统c++看齐,可以使用this当一般变量使用. 3 J8 {0 q ?) Y+ ~/ s
, {/ d' g- w4 o0 j6 M# E
-fcond-mismatch
) f3 K" e O8 B; u. i; A 允许条件表达式的第二和第三参数类型不匹配,表达式的值将为void类型
* w! e) ]4 P7 N* m ; J" S9 _" s) A/ [. I: f7 I+ P$ \
-funsigned-char
& w$ T2 `& n( o$ I) A-fno-signed-char
0 ?) Y. j; }, ^4 h7 d" l-fsigned-char + y/ h! x$ X* k
-fno-unsigned-char
5 ]) R5 Q( I3 y2 m6 w' V 这四个参数是对char类型进行设置,决定将char类型设置成unsigned char(前两个参
7 `' Q$ {+ f1 |& n8 W' ^数)或者 signed char(后两个参数)
0 C) B+ S7 H8 E( r
" {( [2 ]3 H5 L1 H9 [# h-include file 9 e D/ `3 m, r# X! S
包含某个代码,简单来说,就是便以某个文件,需要另一个文件的时候,就可以用它设 . @7 i( ?0 K d( X" T
定,功能就相当于在代码中使用#include<filename>
) e, o2 k3 a1 ^ Q8 y: @ 例子用法:
, ]* i ?0 M e% X, j; \& Y gcc hello.c -include /root/pianopan.h
5 b( h: S- K; k* w$ G1 b; u# V- {
3 M0 a; n7 b2 i: @1 h-imacros file
0 w- W8 h# a1 ] 将file文件的宏,扩展到gcc/g++的输入文件,宏定义本身并不出现在输入文件中
+ K9 l5 V" o) B( d) f
% L7 Q( [6 }+ r' j-Dmacro 8 Z: N& _& R& X" S/ k
相当于C语言中的#define macro
; a* ^3 `0 Z+ ]: s4 D8 l
3 ~3 T) b, n! m- A-Dmacro=defn
y1 n1 D. N% P+ t# B* J; b3 e' ` 相当于C语言中的#define macro=defn 5 p! z' j1 z' K7 b2 G, t
0 w6 F' V1 N0 }4 p-Umacro " G& c: K% g3 e2 Q3 [
相当于C语言中的#undef macro 0 k+ { f8 [' L% g( r
-undef
" E% _. p" E0 ^% h5 B7 A, B& g& H 取消对任何非标准宏的定义 # o* j6 Z- U1 O3 K
8 n2 I8 ^; t# s
-Idir 9 S( m; X0 d& G" V. B
在你是用#include"file"的时候,gcc/g++会先在当前目录查找你所制定的头文件,如 & S; t/ w8 r! E3 c' T3 Y; k
果没有找到,他回到缺省的头文件目录找,如果使用-I制定了目录,他
5 K ^( @% p: I8 {9 h$ i* G7 p g 回先在你所制定的目录查找,然后再按常规的顺序去找.
6 _$ _. ]4 n% J! u 对于#include<file>,gcc/g++会到-I制定的目录查找,查找不到,然后将到系统的缺
! W+ {2 p0 U7 ^, f& L$ U( g省的头文件目录查找 % ]) d. F0 d4 F) H* }% O, N; u
; H' T& w0 Y# O) ~: `+ J2 ?
-I- - b3 O9 D; E" h
就是取消前一个参数的功能,所以一般在-Idir之后使用
/ _! S. \/ {5 S- d! i0 @- n# ]
0 j: ^6 H& w. T- n-idirafter dir
1 q# a* K4 A6 ^% a. _ 在-I的目录里面查找失败,讲到这个目录里面查找.
8 l2 ~' j. D6 u
# ?+ r# E/ ?( q# |# l: ^# Z-iprefix prefix + R ` Z: r6 X: n
-iwithprefix dir
+ {$ b5 X o9 b$ a% z: V 一般一起使用,当-I的目录查找失败,会到prefix+dir下查找 2 F* K( P' x) ]2 t7 N U8 o
- n3 C* C/ V: y; {% s-nostdinc
6 m& T- r2 l. L& b1 k 使编译器不再系统缺省的头文件目录里面找头文件,一般和-I联合使用,明确限定头
8 B$ \& D# H, V1 w* c' r. T5 A& C6 M文件的位置 " U# R& `! x$ k3 z" t
# p( m8 c' \$ n- S8 G: T-nostdin C++
) K3 X. Z2 @5 y C$ J3 h; B8 n 规定不在g++指定的标准路经中搜索,但仍在其他路径中搜索,.此选项在创libg++库 7 t5 i: V0 b; J* ^; K9 W. x
使用
7 ~% ?$ p; x& [ k: r& j2 s3 S* [2 f + [6 O3 ?$ Q% g6 a0 m7 c
-C 5 {- K, n- i8 f8 e( F
在预处理的时候,不删除注释信息,一般和-E使用,有时候分析程序,用这个很方便的
6 H; J1 u) T: K2 [% O C" r+ Q5 ]" a K# |1 f* ]0 v
( ^% s0 ]2 q4 p$ h0 i$ \' B X5 p-M
) L% s H, l5 m% F3 Y6 {( @1 g9 v 生成文件关联的信息。包含目标文件所依赖的所有源代码你可以用gcc -M hello.c
: B K2 }. I3 @: \" V+ G8 k7 n来测试一下,很简单。
7 Q0 Q# Y; {- E% B5 X ) U1 ^; i5 C1 e' l% z
-MM / F+ H4 }7 }5 R3 G
和上面的那个一样,但是它将忽略由#include<file>造成的依赖关系。 ' X. U# ?: W- X
8 E! c' R4 k* g( ~4 c9 e# C
-MD 5 i; _8 X9 o5 E9 r. u
和-M相同,但是输出将导入到.d的文件里面
$ M% u4 g+ t3 I% C3 U; ^ / n5 b. I2 L+ i. M
-MMD . u0 B6 u0 d1 S8 K5 H3 g
和-MM相同,但是输出将导入到.d的文件里面 . i- y5 Y. S( k' j
7 o( }2 i/ p8 X) Y3 u0 |
-Wa,option
/ N- f( T8 D3 G! R. O! i+ \ 此选项传递option给汇编程序;如果option中间有逗号,就将option分成多个选项,然
6 \: M( \4 ?! Z后传递给会汇编程序 l/ A/ c' @. G/ N; K# M
6 \$ k$ Q0 I2 y4 {* k( R! U-Wl.option 1 [* @1 X! E- H
此选项传递option给连接程序;如果option中间有逗号,就将option分成多个选项,然 : Y _! [. L8 N* p0 [) r% g
后传递给会连接程序.
% o+ n* h# e6 G0 C ; X* U* P# o# h0 U! ~; p0 ~
-llibrary
4 N: @( u/ v2 J 制定编译的时候使用的库
& c- L& E! u' ` 例子用法
1 m9 O3 W, N' B" G( Y gcc -lcurses hello.c
2 y( p" o, _8 J/ r ] 使用ncurses库编译程序
7 j3 r) k% M. n6 u ) Y1 u( f9 s' d; o- y
-Ldir
5 X6 a' @- q( _ `+ R 制定编译的时候,搜索库的路径。比如你自己的库,可以用它制定目录,不然
% ~5 x E, X" L7 V9 M' `" W 编译器将只在标准库的目录找。这个dir就是目录的名称。
' S2 t2 r" d7 W6 N& V0 a
% x3 v+ I+ l4 { w. S0 @+ y-O0
/ x. v2 [! Z% u: M-O1
: i/ C4 |+ Q. d! _- B/ e: }8 Q' s) C-O2 , w- |" |. Y4 p) E
-O3
) i3 S/ G/ M* g7 x5 M; J' q 编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高
" a7 f" y7 x) h3 s6 { c3 @# v* a) g; D % W+ m W) ]" y2 J1 v7 [
-g
+ W7 S' q4 S7 C% y8 ~1 V" { 只是编译器,在编译的时候,产生调试信息。
, ^, ^- z, V3 J+ u+ ]+ t " @" v2 _( J' D; r( R. ]" e6 {7 m
-gstabs
1 f1 H. U4 V1 W 此选项以stabs格式声称调试信息,但是不包括gdb调试信息. ! G. f$ Q& Q3 O) ~" p
# }9 S" [& y- q( k$ v% }9 t-gstabs+
7 D' [6 c4 |3 i' [ 此选项以stabs格式声称调试信息,并且包含仅供gdb使用的额外调试信息. - _8 h% p# b- T3 X& a0 g
# C7 ]1 \4 E, z* d+ W-ggdb 9 j$ h3 Y& [( S$ V4 `$ a& V
此选项将尽可能的生成gdb的可以使用的调试信息. 6 g' y0 d i& _4 Z; W
-static
7 N( ]1 L+ g1 T; G 此选项将禁止使用动态库,所以,编译出来的东西,一般都很大,也不需要什么 9 i/ t4 O" \7 m: j9 d( H
动态连接库,就可以运行. + R( m) y; N) o R A( p
-share . v- q" D4 [/ ^9 h. M2 D8 A- M4 c
此选项将尽量使用动态库,所以生成文件比较小,但是需要系统由动态库. 8 G3 a; Y- f0 u+ N
-traditional
; @8 W. ` \9 h$ m' j& l0 y8 M0 s 试图让编译器支持传统的C语言特性 ' ?$ w& [; j+ ~2 P4 o, [/ x
[参考资料]
5 Z4 b: N5 S1 @-Linux/UNIX高级编程
# G* _1 M* R" }, M9 c7 h 中科红旗软件技术有限公司编著.清华大学出版社出版
/ ~" q5 q; N& e1 E% W3 D-Gcc man page ' h3 |- b1 l! |. G4 M
, u7 |3 p1 n7 G" d' M ^0 B- |5 f
[ChangeLog]
( d* F. \" H* }; |$ s" L-2002-08-10
$ b5 R! h5 J7 J ver 0.1 发布最初的文档
9 Q6 X! ]4 U( l; p3 C-2002-08-11
. W; ^" t ]5 {. _ ver 0.11 修改文档格式 # x* `& L, I9 i. S" s: Q
-2002-08-12
4 J$ v, T8 _" c. m ver 0.12 加入了对静态库,动态库的参数 " y- D6 f3 i2 V; {+ [& `6 [
-2002-08-16 , R5 {5 b, j3 V$ z" v! |: h+ A w
ver 0.16 增加了gcc编译的4个阶段的命令 * b$ t5 N+ R$ o/ |3 ?
运行 gcc/egcs
) l g8 Y( L3 G**********运行 gcc/egcs*********************** ; Y5 j5 C2 C/ Q
GCC 是 GNU 的 C 和 C++ 编译器。实际上,GCC 能够编译三种语言:C、C++ 和 O
. ]9 G+ g, X! r3 f) e" G" T Xbject C(C 语言的一种面向对象扩展)。利用 gcc 命令可同时编译并连接 C 和 C++ 6 @) r2 @. e& B; V8 T: ?4 r, J
源程序。 9 X# }- @& x2 p4 p: \6 j
如果你有两个或少数几个 C 源文件,也可以方便地利用 GCC 编译、连接并生成可
; G* @' U1 c B4 Y* D6 F: A. _执行文件。例如,假设你有两个源文件 main.c 和 factorial.c 两个源文件,现在要编
' E7 t1 Z! S% `2 p) ]3 F译生成一个计算阶乘的程序。
3 P1 Y+ U$ e4 o* v8 u, m# p" _代码:
0 N* B! L! c, \----------------------- 2 R/ L- L3 s( ]. ~
清单 factorial.c
! C7 k* g) m O% F----------------------- ( J8 X* ]: x. [/ x8 I1 k( D
int factorial (int n)
' C& k9 g' o; a* g* M6 U" p; V{ 4 H$ @4 y, Q3 G1 Y3 ~0 H# r! ?
if (n <= 1) * g* t9 W/ ~* G* e2 L5 z
return 1; 4 X) Y- Q6 p: W. {) M
else
; W+ D! Z" M( { return factorial (n - 1) * n; C3 C. Z3 b! j% A/ O$ N J
} % H5 f( L J% p+ m
----------------------- h1 U' R6 A* X' h3 O" I$ r
清单 main.c
$ I, u0 `6 `3 j& B----------------------- 4 h1 P4 U& B+ q
#include <stdio.h>
# |% n4 \; X/ s. J( P) y& ~#include <unistd.h>
5 J4 Q' `3 o9 m5 E9 `( s- Y- a9 Uint factorial (int n); 5 }* {5 @6 o! M' {9 G
int main (int argc, char **argv) 7 R4 P; t. a2 c( l$ y0 C
{ 0 p+ d2 C2 }" g, J- f6 F6 R
int n; . ] u: j/ p. e" g/ A4 t
if (argc < 2) + I: Y1 F: w. D- k- p
{ 5 O! L( D- q R8 M
printf ("Usage: %s n\n", argv [0]); " ^3 m7 C% G$ S& {# }9 k! K
return -1; 6 G' K6 K6 ~% l
} & Q+ e: x' ^( N, T0 b% J0 ?
else 5 U$ P e# M* ]( W% P( ?! m
{ 6 E$ V/ M; j4 D* e7 Q( w
n = atoi (argv[1]);
: l7 q* Q* f8 Q7 Q+ | printf ("Factorial of %d is %d.\n", n, factorial (n)); 2 O5 ~- Y X E+ g: _& N. B4 q
} 6 }. p: s9 p$ c. F! P Z c& e
return 0;
1 s2 r, S4 f% d' ?% Z& z}
$ w$ X d4 ~- n- K-----------------------
+ U+ J# q) G% c& y3 D+ a! y利用如下的命令可编译生成可执行文件,并执行程序: - `- n5 E. C! n t
$ gcc -o factorial main.c factorial.c
( e' A" \) j! d9 r5 N$ ./factorial 5
% N: n Q0 p" W- ^& K5 G7 vFactorial of 5 is 120.
0 P. y5 y7 }" o& {3 H7 @ S GCC 可同时用来编译 C 程序和 C++ 程序。一般来说,C 编译器通过源文件的后缀 3 w; F" ^ m1 A/ Q
名来判断是 C 程序还是 C++ 程序。在 Linux 中,C 源文件的后缀名为 .c,而 C++ 源 1 d# E; K" _, D: N/ ^6 D
文件的后缀名为 .C 或 .cpp。但是,gcc 命令只能编译 C++ 源文件,而不能自动和 C ' F, o- v0 e- z
++ 程序使用的库连接。因此,通常使用 g++ 命令来完成 C++ 程序的编译和连接,该程 & A3 n* @" ?" g. k. g2 b
序会自动调用 gcc 实现编译。假设我们有一个如下的 C++ 源文件(hello.C): 9 E. q/ y+ L9 p$ n( l' b7 i- S* x
#include <iostream> 1 }% U2 l4 E% F$ o5 e, t
void main (void)
]3 a- B3 t4 D) Z+ V+ t R& [{
4 m6 @4 y: H9 U3 N/ m3 K cout << "Hello, world!" << endl;
+ C7 G4 `2 ?- W, e B" n' {' B}
$ J- K/ F% v$ N0 k+ Z$ E6 h. u则可以如下调用 g++ 命令编译、连接并生成可执行文件: $ A9 a c- R: E* H
$ g++ -o hello hello.C 9 }3 |6 d, u. r6 w
$ ./hello
: g% y6 J5 O4 b/ o6 @1 G. THello, world!
6 G% e: ^# N8 k$ b**********************gcc/egcs 的主要选项*********
4 i& q7 Q; D0 U9 f" Y& Xgcc 命令的常用选项 0 v3 f5 R$ h0 l4 x' P
选项 解释
/ f/ r7 ^' Q8 Y* r9 U. A1 F-ansi 只支持 ANSI 标准的 C 语法。这一选项将禁止 GNU C 的某些特色,
& l9 t" [! \( n2 T( M1 t例如 asm 或 typeof 关键词。
, Y# ~( h( T/ Q0 |-c 只编译并生成目标文件。 ! Y- y+ a. a6 c8 \* L) a. w
-DMACRO 以字符串“1”定义 MACRO 宏。
3 J# b5 z G$ |/ d$ w$ M-DMACRO=DEFN 以字符串“DEFN”定义 MACRO 宏。 $ L. }1 y a2 U8 e8 x
-E 只运行 C 预编译器。 . O! @8 D0 c; |, T
-g 生成调试信息。GNU 调试器可利用该信息。 ( K/ i$ a8 K& I$ f+ s8 z
-IDIRECTORY 指定额外的头文件搜索路径DIRECTORY。
. I9 s# L% V4 s0 K-LDIRECTORY 指定额外的函数库搜索路径DIRECTORY。 2 H5 a, X8 d6 w2 V/ ^& C$ M( K
-lLIBRARY 连接时搜索指定的函数库LIBRARY。 0 S+ M6 F3 t! l T! |4 D
-m486 针对 486 进行代码优化。
% |7 V6 n" Z6 m# I* d2 G3 Y6 L-o FILE 生成指定的输出文件。用在生成可执行文件时。 - k/ a7 w* F! c) H, m* A q) M6 m$ Z% ?
-O0 不进行优化处理。 , f" C# X( C: M" g8 B
-O 或 -O1 优化生成代码。 5 I2 T& ]- S- h k
-O2 进一步优化。 - ?) t2 F& ?/ E9 u
-O3 比 -O2 更进一步优化,包括 inline 函数。 & |- [0 w/ }4 s6 L7 o
-shared 生成共享目标文件。通常用在建立共享库时。
) m5 o' J% Q. f1 [( w" L; a, I-static 禁止使用共享连接。
5 z# V9 d6 R& p* P0 \- p& D/ h-UMACRO 取消对 MACRO 宏的定义。
- ~7 A5 _8 s4 `9 X2 b9 A4 _-w 不生成任何警告信息。 : S* O5 e# O( [ _! E# K$ p
-Wall 生成所有警告信息。5 _3 t+ }, T( G, Z9 m
|
|