关于gcc:
1.编译过程
编译过程是分为四个阶段进行的,即预处理(也称预编译,Preprocessing)、编译(Compilation)、汇编 (Assembly)和连接(Linking)。
- 预处理
gcc -E hello.c -o hello.i 或 gcc -E hello.c
生成文件(部分):
gcc的-E选项,可以让编译器在预处理后停止,并输出预处理结果。在本例中,预处理结果就是将stdio.h 文件中的内容插入到hello.c中了。
- 编译为汇编代码(Compilation)
预处理之后,可直接对生成的hello.i文件编译,生成汇编代码:
gcc -S hello.i -o hello.s
gcc的-S选项,表示在程序编译期间,在生成汇编代码后,停止,-o输出汇编代码文件。
- 汇编(Assembly)
对于上一小节中生成的汇编代码文件hello.s
gcc -c hello.s -o hello.o
这是因为生成的是二进制文件
- 连接(Linking)
对于上一小节中生成的hello.o,将其与C标准输入输出库进行连接,最终生成程序hello
gcc hello.o -o hello
在命令行窗口中,执行./hello, 让它说HelloWorld吧!
2.多个程序文件的编译
通常整个程序是由多个源文件组成的,相应地也就形成了多个编译单元,使用gcc能够很好地管理这些编译单元。假设有一个由hello1.c和 hello2.c两个源文件组成的程序,为了对它们进行编译,并最终生成可执行程序hello,可以使用下面这条命令:
gcc hello1.c hello2.c -o hello
如果同时处理的文件不止一个,gcc仍然会按照预处理、编译和链接的过程依次进行。如果深究起来,上面这条命令大致相当于依次执行如下三条命令:
gcc -c hello1.c -o hello1.o
gcc -c hello2.c -o hello2.o
gcc hello1.o hello2.o -o hello
3.库文件连接
开发软件时,完全不使用第三方函数库的情况是比较少见的,通常来讲都需要借助许多函数库的支持才能够完成相应的功能。从程序员的角度看,函数库实际上就是一些头文件(.h)和库文件(so、或lib、dll)的集合。。虽然Linux下的大多数函数都默认将头文件放到/usr/include/目录下,而库文件则放到/usr/lib/目录下;Windows所使用的库文件主要放在Visual Stido的目录下的include和lib,以及系统文件夹下。但也有的时候,我们要用的库不再这些目录下,所以gcc在编译时必须用自己的办法来查找所需要的头文件和库文件。
例如我们的程序hello.c是在linux上使用c连接mysql,这个时候我们需要去mysql官网下载MySQL Connectors的C库,下载下来解压之后,有一个include文件夹,里面包含mysql connectors的头文件,还有一个lib文件夹,里面包含二进制so文件libmysqlclient.so
其中inclulde文件夹的路径是/usr/dev/mysql/include,lib文件夹是/usr/dev/mysql/lib
- 编译成可执行文件
首先我们要进行编译hello.c为目标文件,这个时候需要执行
gcc –c –I /usr/dev/mysql/include hello.c –o hello.o
- 链接
最后我们把所有目标文件链接成可执行文件:
gcc –L /usr/dev/mysql/lib –lmysqlclient hello.o –o hello
Linux下的库文件分为两大类分别是动态链接库(通常以.so结尾)和静态链接库(通常以.a结尾),二者的区别仅在于程序执行时所需的代码是在运行时动态加载的,还是在编译时静态加载的。
强制链接时使用静态链接库
默认情况下, GCC在链接时优先使用动态链接库,只有当动态链接库不存在时才考虑使用静态链接库,如果需要的话可以在编译时加上-static选项,强制使用静态链接库。在/usr/dev/mysql/lib目录下有链接时所需要的库文件libmysqlclient.so和libmysqlclient.a,为了让GCC在链接时只用到静态链接库,可以使用下面的命令:
gcc –L /usr/dev/mysql/lib –static –lmysqlclient test.o –o test
静态库链接时搜索路径顺序:
- ld会去找GCC命令中的参数-L
- 再找gcc的环境变量LIBRARY_PATH
- 再找内定目录 /lib /usr/lib /usr/local/lib 这是当初compile gcc时写在程序内的
动态链接时、执行时搜索路径顺序:
- 编译目标代码时指定的动态库搜索路径
- 环境变量LD_LIBRARY_PATH指定的动态库搜索路径
- 配置文件/etc/ld.so.conf中指定的动态库搜索路径
- 默认的动态库搜索路径/lib
- 默认的动态库搜索路径/usr/lib
有关环境变量:
LIBRARY_PATH环境变量:指定程序静态链接库文件搜索路径
LD_LIBRARY_PATH环境变量:指定程序动态链接库文件搜索路径
[常用参数详解]
-c
只激活预处理,编译,和汇编,也就是只把程序做成obj文件
gcc -c hello.c
将生成.o的obj文件
-S
只激活预处理和编译,就是指把文件编译成为汇编代码。
gcc -S hello.c
将生成.s的汇编代码,你可以用文本编辑器察看
-E
只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里面.
-o
制定目标名称,缺省的时候,gcc 编译出来的文件是a.out,很难听,如果你和我有同感,改掉它,哈哈
-include file
包含某个代码,简单来说,就是便以某个文件,需要另一个文件的时候,就可以用它设定,功能就相当于在代码中使用#include
gcc hello.c -include /root/pianopan.h
-C
在预处理的时候,不删除注释信息,一般和-E使用,有时候分析程序,用这个很方便的
-Ldir
制定编译的时候,搜索库的路径。比如你自己的库,可以用它制定目录,不然编译器将只在标准库的目录找。这个dir就是目录的名称。
-O0
-O1
-O2
-O3
编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高
-g
只是编译器,在编译的时候,产生调试信息。
-static
此选项将禁止使用动态库,所以,编译出来的东西,一般都很大,也不需要什么动态连接库,就可以运行.
-share
此选项将尽量使用动态库,所以生成文件比较小,但是需要系统由动态库.
对gcc的总结:
-E :让GCC仅进行预处理后就不继续作下去了
-S :让GCC仅进行预处理,编译后就不继续作下去了
-c :让GCC仅进行预处理,编译,汇编后就不继续作下去了
-o Ouput:指定输出文件,默认gcc编译输出的程序名为a.out.
-I dir,-Idir:追加目录dir到头文件的搜索路径中
-L dir,-Ldir:追加目录dir到库文件的搜索路径中
-l library:指定使用的库文件,默认gcc在编译一个程序时只连接到标准c库上,是用该选项能够使他连接到指定的库上,例如若你要连接到数学库上(libm.a)则你只须指定 -lm就可以了。也就是说这个选项指定连接的库文件可以将前缀lib和后缀.a(或.so)省略。
关于gdb:
这儿有更好的
总结:
list或l: 列出源码,每次列十行
list加上行号:列出从改行开始的源码
list加上函数名:列出该函数的源码
next或n:单步执行下一条语句
print或p:打印变量的值
step或s:单步执行下一条语句,有函数进入执行