我们知道一个代码写完要变为可执行程序需要经过以下四个步骤
- 预处理(进行宏替换)
- 编译(生成汇编)
- 汇编(生成机器可识别代码)
- 连接(生成可执行文件或库文件)
我们知道在Linux系统不区分文件后缀,因此文本文件可以设置后缀为txt来告诉用户这是一个文本文件,但是对于Linux下的各种程序是区分后缀的,而gcc和g++它们是要看文件后缀的!
- gcc只可以编译C语言
- g++C和C++都可以编译
语法:gcc [选项] 要编译的文件 [选项] [目标文件]
gcc code.c -o code
-o 将处理结果输出到指定文件,该选项后需紧跟输出文件名。(后面会谈到常用选项对应的作用)
- 预处理功能主要包括宏定义,文件包含,条件编译,去注释等。
- 预处理指令是以#号开头的代码行。
- 实例: gcc –E code.c –o code.i
- 选项“-E”,该选项的作用是让 gcc 在预处理结束后停止编译过程。
- 选项“-o”是指目标文件,“.i”文件为已经过预处理的C原始程序
- 在这个阶段中,gcc 首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,gcc 把代码翻译成汇编语言。
- 用户可以使用“-S”选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码
- gcc –S code.i –o code.s
- 汇编阶段是把编译阶段生成的“.s”文件转成目标文件
- 读者在此可使用选项“-c”就可看到汇编代码已转化为“.o”的二进制目标代码了
- gcc -c code.s -o code.o
- 在成功编译之后,就进入了链接阶段。
- gcc code.o -o code
- 链接后生成的也是二进制文件。
注意
- gcc/g++不带-E、-S、-c选项时,就默认生成预处理、编译、汇编、链接全过程后的文件。
- 若不用-o选项指定生成文件的文件名,则默认生成的可执行文件名为a.out。
- -E 只进行预处理,这个不生成文件,你需要把他重定向到一个输出文件里面(否则将把预处理后的结果打印到屏幕上)。
- -S 编译到汇编语言,不进行汇编和链接,即只进行预处理和编译。
- -c 编译到目标代码
- -o 将处理结果输出到指定文件,该选项后需紧跟输出文件名。
- -static 此选项对生成的文件采用静态链接。
- -g 生成调试信息(若不携带该选项则默认生成release版本)。
- -shared 此选项将尽量使用动态库,生成文件较小。
- -w 不生成任何警告信息。
- Wall 生成所有警告信息。
- -O0/-O1/-O2/-O3 编译器优化选项的四个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高。
小tips:如果出现下面这种情况
//安装指令
sudo yum install glibc -static //c静态库
sudo yum install libstdc++ -static //c++静态库
在Linux当中gcc/g++默认生成的可执行程序是release版本的,是不可被调试的。如果想生成debug版本,就需要在使用gcc/g++生成可执行程序时加上-g选项。
gdb使用语法 gdb + 文件名
调试
显示
断点
退出
依赖关系 :
文件A的变更会影响到文件B,那么就称文件B依赖于文件A。
eg:code.o文件是由code.c文件通过预处理、编译以及汇编之后生成的文件,所以code.c文件的改变会影响code.o,所以说code.o文件依赖于code.c文件。
- 多个源文件如何编译???
- 直接gcc多个源文件进行编译 ,一步到位
- 先用每个源文件各自生成自己的二进制文件,然后再将这些二进制文件通过链接生成可执行程序。gcc -c
若是直接使用源文件生成可执行程序,那么其中一个源文件进行了修改,再生成可执行程序的时候就需要将所以的源文件重新进行编译链接。
而若是先用每个源文件各自生成自己的二进制文件,那么其中一个源文件进行了修改,就只需重新编译生成该源文件的二进制文件,然后再将这些二进制文件通过链接生成可执行程序即可。
编译链接的时候不需要加上头文件,因为编译器通过源文件的内容可以知道所需的头文件名字,而通过头文件的包含方式(“尖括号”包含和“双引号”包含),编译器可以知道应该从何处去寻找所需头文件。
注: 一般将这种clean的目标文件设置为伪目标,用.PHONY修饰,伪目标的特性是:总是被执行。
- make会在当前目录下找名字为“Makefile”或“makefile”的文件。
- 如果找到,它会找文件当中的第一个目标文件,在上面的例子中,它会找到mytest这个文件,并把这个文件作为最终的目标文件。
- 如果mytest文件不存在,或是mytest所依赖的后面的test.o文件和main.o文件的文件修改时间比mytest文件新,那么它就会执行后面的依赖方法来生成mytest文件。
- 如果mytest所依赖的test.o文件不存在,那么make会在Makefile文件中寻找目标为test.o文件的依赖关系,如果找到则再根据其依赖方法生成test.o文件(类似于堆栈的过程)。
- 当然,你的test.c文件和main.c文件是存在的,于是make会生成test.o文件和main.o文件,然后再用test.o文件和main.o文件生成最终的mytest文件。
- make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。
- 在寻找的过程中,如果出现错误,例如最后被依赖的文件找不到,那么make就会直接退出,并报错。