在Linux环境下进行开发,gcc是非常重要的编译工具,所以学习gcc的基本常见用法时非常有必要的。
一.首先我们先说明下gcc编译源文件的后缀名类型
.c为后缀的文件,C语言源代码文件;
.a为后缀的文件,是由目标文件构成的档案库文件;
.C,.cc或.cxx 为后缀的文件,是C++源代码文件;
.h为后缀的文件,是程序所包含的头文件;
.i 为后缀的文件,是已经预处理过的C源代码文件;
.ii为后缀的文件,是已经预处理过的C++源代码文件;
.m为后缀的文件,是Objective-C源代码文件;
.o为后缀的文件,是编译后的目标文件;
.s为后缀的文件,是汇编语言源代码文件;
.S为后缀的文件,是经过预编译的汇编语言源代码文件。
二.接下来,我们就具体介绍下gcc命令的具体用法了
gcc的基本命令格式是:gcc [options] [filenames]
其中[options]就是编译器需要制定的相应选项,filenames就是相关文件的名称,下面我就介绍下做常用的几个options
(注意:一定要区分编译选项里的大小写,他们时代表不同的含义)
(1) -c :只是进行编译而不连接成为可执行文件,编译器只是由输入的.c等源代码文件生成.o为后缀的目标文件,通常用于编译不包含主程序的子程序文件。
(2) -o output_filename :确定输出的文件的名称为output_filename,如果不给出这个选项,gcc就给出预设的可执行文件a.out。
(3) -g: 产生符号调试工具(GNU的gdb)所必要的符号信息,要想对源代码进行调试,我们就必须加入这个选项。
(4) -O: 对程序进行优化编译、连接,采用这个选项,整个源代码会在编译、连接过程中进行优化处理,这样产生的可执行文件的执行效率可以提高,但是,编译、连接的速度就相应地要慢一些。
(5) -O2 : 比-O更好的优化编译、连接,当然整个编译、连接过程会更慢。
(6) -Idirname: 将dirname所指出的目录加入到程序头文件目录列表中,是在预编译过程中使用的参数。
C程序中的头文件包含两种情况∶
a.#include <myinc.h>
b.#include "myinc.h"
其中a类时使用的是<>来包含头文件,b类则使用“”来包含头文件。他们之间的主要差别是:对于a类,预处理程序源文件在系统预设包含文件目录(如/usr/include等等)中搜寻相应的文件,而对于b类,源文件则在当前目录中搜寻头文件,这个选项的作用是告诉源文件,如果在当前目录中没有找到需要的头文件,就到指定的dirname目录中去寻找。在程序设计中,如果我们需要的这种包含文件分别分布在不同的目录中,就需要逐个使用-I选项给出搜索路径。
(7) -Ldirname: 将dirname所指出的目录加入到程序函数链接库文件的目录列表中,它是在连接过程中使用的参数。在预设状态下,连接程序ld在系统的预设路径中(如/usr/lib)寻找所需要的链接库文件。而这个选项告诉连接程序,首先到-L指定的目录中去寻找,然后再到系统预设路径中寻找,如果函数库存放在多个目录下,就需要依次使用这个选项,给出相应的存放目录。
(8) -lname: 程序在连接时,装载名字为“libname.a”的函数库,该函数库位于系统预设的目录或者由-L选项确定的目录下。例如,-lm表示连接名为“libm.a”的数学函数库,
"-lpthread"则表示链接线程函数链接库文件。
(9) -shared:这主要是在生成共享库文件时使用。
(10) -Wall : 生成所有警告信息。
(11) -w : 不生成任何警告信息。
(12) -S : 生成汇编语言文件。
三.最后,我还想向大家阐明下平时大家都没怎么注意的一个问题-------gcc是怎么查找源文件中的头文件和链接时所需的链接库文件
(1) 查找头文件
step1:在源文件所在的目录下进行查找
step2:在我们在编译程序用选项“-Idirname”所指的路径去寻找头文件。
step3:查找gcc相关的环境变量所设置的路径:C_INCLUDE_PATH,CPLUS_INCLUDE_PATH,OBJC_INCLUDE_PATH
step4:查找gcc内定的目录:
/usr/include
/usr/local/include
/usr/lib/gcc-lib/i386-linux/2.95.2/include
(2) 查找动态链接库
什么时链接库?我再罗嗦一句吧。就像我们C语言中常用的printf函数为例,你们知道printf函数是怎么实现的吗?其实它是系统把这些函数实现都被做到名为libc.so.6的库文件中去了,在没有特别指定时,gcc会到系统默认的搜索路径”/usr/lib”下进行查找,也就是链接到libc.so.6库函数中去,这样就能实现函数”printf”了,而这也就是链接的作用。其中函数库又分为静态函数库和动态函数库两种。静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了。其后缀名一般为”.a”。动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销。动态库一般后缀名为”.so”,如前面所述的libc.so.6就是动态库。
好了,言归正传,其实动态链接库的查找过程其实和查找头文件类似。
step1: 在选项“-Ldirname”所指定的目录中查找。
step2: gcc的环境变量LIBRARY_PATH指定的路径中查找。
step3: 在gcc内定的目录中查找,如 /usr/lib/ /usr/local/lib/