GCC - My GCC Manual
1. gcc/g++ 工作原理
1.1. gcc/g++生成可执行文件的完整步骤
预处理(preprocessing) è
编译 (compilation) è
汇编 (assembly) è
连接 (linking)
Tips:
编译:将预处理后的语句翻译成汇编语言。
汇编:把汇编语言翻译成机器语言的过程称为汇编。
1.2. 源文件后缀名指出语言种类和后期操作
● 非连接器(linker)阶段-编译器(compiler)阶段
.c è C源程序 |
预处理,编译,汇编 |
.C è C++源程序 |
预处理,编译,汇编 |
.cc è C++源程序 |
预处理,编译,汇编 |
.cxx è C++源程序 |
预处理,编译,汇编 |
.cpp è C++源程序 |
预处理,编译,汇编 |
.cp è C++源程序 |
预处理,编译,汇编 |
.CPP è C++ |
预处理,编译,汇编 |
.m è Objective-C源程序 |
预处理,编译,汇编 |
.i è 预处理后的C文件 |
编译,汇编 |
.ii è 预处理后的C++文件 |
编译,汇编 |
.s è 汇编语言源程序 |
汇编 |
.S è 汇编语言源程序 |
预处理,汇编 |
.h è C预处理器文件 |
预处理 |
.hh è C预处理器文件 |
预处理 |
.H è C预处理器文件 |
预处理 |
PS:
非连接器阶段处理结束讲生成连接器阶段的文件
● 连接器(linker)阶段
.o 目标文件(Object File)
.a 归档库文件(Archive File)
2. gcc/g++ 常用命令详解
2.1. 总体选项(Overall Option)
选项 |
说明 |
实例 |
-x [language] |
● 明确指出后面输入文件的语言类型为language,而不是从文件名后缀得到的默认选择。 ● 这个选项应用于后面所有的输入文件,直到遇着下一个`-x'选项。 ● language的可选值有 ‘c’ è c语言 ‘objective-c’ è 扩展c的ObjC语言 ‘c-header’ è ‘c++’ è c++语言 ‘cpp-output’ è ‘assembler’ è 汇编语言 ‘assembler-with-cpp’ è |
|
-x none |
关闭任何对语种的明确说明,依据文件名后缀处理后面的文件(就像是从未使用过‘-x’选项)。 |
|
-c (compile) |
● 编译或汇编源文件,但是不作连接。编译器输出对应于源文件的目标文件。 ● 缺省情况下, GCC通过用‘.o’替换源文件名后缀‘.c’、‘.i’、‘.s’,等等,产生目标文件名。 ● 可以使用-o选项选择其他名字。 ● GCC忽略-c选项后面任何无法识别的输入文件(他们不需要编译或汇编) |
[命令] gcc -c HelloWorld.c [生成文件] HelloWorld.o
[命令] gcc -c HelloWorld.c -o HiWorld.o [生成文件] HiWorld.o |
-o [file] (output) |
● 指定输出文件为file。该选项不指定GCC产生什么输出——无论是可执行文件、目标文件、汇编文件还是预处理后的C代码。 ● 如果没有使用‘-o’选项,默认的输出结果是:可执行文件为‘a.out’。 |
[命令] gcc HelloWorld.c [生成文件] a.out
[命令] gcc HelloWorld.c [生成文件] a.out
[命令] gcc HelloWorld.c -o HelloWorld.out [生成文件] HelloWorld.out
[命令] gcc HelloWorld.o -o HelloWorld.out [生成文件] HelloWorld.out |
-S |
● 生成汇编文件。编译后即停止,不进行汇编。对于每个输入的非汇编语言文件,输出文件是汇编语言文件。 ● GCC忽略任何不需要编译的输入文件。 |
[命令] gcc -S HelloWorld.c [生成文件] HelloWorld.s
[命令] gcc -S HelloWorld.c -o HiWorld.s [生成文件] HiWorld.s |
-E |
● 预处理后即停止,不进行编译。预处理后的代码送往标准输出。 ● GCC忽略任何不需要预处理的输入文件。 |
|
2.2. 语言选项(LANGUAGE OPTIONS)
选项 |
说明 |
实例 |
-ansi |
支持符合ANSI标准的C程序。 ● 这样就会关闭GNU C中某些不兼容ANSI C的特性,例如asm、inline、typeof等关键字,以及诸如unix和vax这些表明当前系统类型的预定义宏。同时开启不受欢迎和极少使用的ANSI trigraph特性,以及禁止‘$’成为标识符的一部分。 ● 使用‘-ansi’选项不会自动拒绝编译非ANSI程序,可以增加‘-pedantic’选项作为‘-ansi’选项来实现。 ● 使用‘-ansi’选项的时候,预处理器会预定义一个__STRICT_ANSI__宏。有些头文件关注此宏以避免声明某些函数,或者避免定义某些宏。这些函数和宏不被ANSI标准调用——这样就不会干扰在其他地方使用这些名字的程序了。 |
|
2.3. 预处理器选项(Preprocessor Option)
选项 |
说明 |
实例 |
2.4. 警告选项(WARNING OPTION)
选项 |
说明 |
实例 |
-w |
禁止所有警告信息。 |
|
-Wall |
打开所有警告信息。 |
|
2.5. 连接器选项(LINKER OPTION)
函数库分为静态库和动态库两种。静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在。
(1) 静态链接库
● 静态库文件名的命名规范是以lib为前缀,紧接着跟静态库名,扩展名为.a。例如:我们将创建的静态库名为myhello,则静态库文件名就是libmyhello.a。在创建和使用静态或库时,需要注意这点。
● 无论静态库还是动态库,都是由.o文件创建的。因此我们必须将源程序通过gcc将源文件先编译成.o文件。
● 静态链接库其实是归档文件(Archieve File)。创建静态库用ar命令:
#ar crv libmyhello.a hello.o
● 使用静态链接库:
#gcc main.c libmyhello.a -o main 等价于
#gcc -o main main.c –L. –lmyhello
● 静态库链接时搜索路径顺序:
找GCC命令中的参数-L è 找gcc的环境变量LIBRARY_PATH(指定程序静态链接库文件搜索路径) è 找内定目录/lib /usr/lib /usr/local/lib这是当初compile gcc时写在程序内的。
(2) 动态链接库
● 动态库文件名命名规范和静态库文件名命名规范类似,也是在动态库名增加前缀lib,但其文件扩展名为.so。例如要创建的动态库名为myhello,则动态库文件名就是libmyhello.so。
● 无论静态库还是动态库,都是由.o文件创建的。因此我们必须将源程序通过gcc将源文件先编译成.o文件。
● 创建动态链接库:# gcc -shared -fPCI -o libmyhello.so hello.o
● 使用动态链接库:
# gcc -o hello main.c –L. –lmyhello (注意-L后面有个.表示的是当前目录)
● 动态库链接时搜索路径顺序:
找GCC命令中的参数-L è 环境变量LD_LIBRARY_PATH指定的动态库搜索路径 è 配置文件/etc/ld.so.conf中指定的动态库搜索路径 è
默认的动态库搜索路径/lib èè默认的动态库搜索路径/usr/lib。
Tips:
当静态库和动态库同名时, gcc命令将优先使用动态库。
选项 |
说明 |
实例 |
-l [library] |
● 连接名为library的库文件。 ● 库名跟真正的库文件名的关系:拿数学库来说——库名是m,他的动库文件名是libm.so,静态库文件名师libm.a。很容易看出把库文件名的头lib和尾.so去掉就是库名了 ● 指定‘-l’选项和指定文件名的唯一区别是, ‘-l’选项用‘lib’和‘.a’把library包裹起来,而且搜索一些目录。 |
#gcc -o main main.c –L. –lmyhello 在当前路径下连接libmyhello.so 或者 libmyhello.a |
-L [directory] |
● 显示指定库搜索路径。 ● 放在/lib和/usr/lib和/usr/local/lib里的库直接用-l参数就能链接了。但如果库文件没放在这三个目录里,而是放在其他目录里,这时我们只用-l参数的话,链接会出错,出错信息大概是:“/usr/bin/ld: cannot find –lxxx”,也就是链接程序ld在那3个目录里找不到libxxx.so,这时另外一个参数-L就派上用场了。 ●比如常用的X11的库,它在/usr/X11 R6/lib目录下,我们编译时就要用-L/usr/X11R6/lib -lX11参数。-L参数跟着的是库文件所在的目录名。再比如我们把libtest.so放在/aaa/bbb/ccc目录下,那链接参数就是-L/aaa/bbb/ccc –ltest。 |
#gcc -o main main.c –L. –lmyhello 在当前路径下连接libmyhello.so 或者 libmyhello.a |
-shared |
生成一个共享目标文件,他可以和其他目标文件连接产生可执行文件。该选项指定生成动态连接库。 |
# gcc -shared -fPCI -o libmyhello.so hello.o
|
–fPIC |
产生与位置无关的代码并能被加载到任何地址。表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的。 |
# gcc -shared -fPCI -o libmyhello.so hello.o
|
2.6. 目录选项(DIRECTORY OPTION)
选项 |
说明 |
实例 |
-I [directory] |
在头文件的搜索路径列表中添加directory目录。 |
|
2.7. 调试选项(DEBUGGING OPTION)
选项 |
说明 |
实例 |
-g |
以操作系统的本地格式(stabs, COFF, XCOFF,或DWARF)产生调试信息。GDB能够使用这些调试信息。 |