Makefile学习笔记03|g++编译的四个步骤
??希望看到这篇文章的朋友能在评论区留下宝贵的建议来让我们共同成长,谢谢。
介绍
??GCC(G++)编译的四个步骤分别是预处理(Preprocessing)、编译(Compilation)、汇编(Assembly)、链接(Linking)。 ??我们在配置项目时,首先要了解一个项目是如何一步步被编译出来的,是怎样从源码编译出可执行程序,最终又是如何被执行的。只有理清了其中的关系,我们才能快速定位问题,从而解决在编译中出现的问题。 ??g++编译的四个步骤中,编译与汇编对编写makefile来说不太重要(跨平台编译时很重要)。 ??首先,预处理时,g++会把所有的文件关联起来,主要包括宏定义与头文件的声明。其实预处理就是把所有的源码的头文件展开,完成宏定义的替换,一一对应地生成更完整的"cpp"文件。此时可能出现关于头文件包含、宏定义相关的错误。 ??然后是编译。编译是将预处理生成的文件转化成为汇编码,这时相应的语法错误就会开始出现。编译是针对单个cpp文件进行的,并不是针对整个项目,所以在此时发生关联性的错误时是不会报错的。 ??接下来是汇编。汇编将汇编码翻译成二进制代码,生成.o文件(在Windows环境下生成的是.obj文件)。针对汇编部分,有很多工具将其进行了优化,可以将编译与汇编两个步骤分开,但是为了方便,下面的演示中就不将编译与汇编分开了。此时CPU已经可以读懂生成的.o文件了,但是还不可以运行。因为CPU想要运行程序,需要先找到入口函数、有时还需要有必要的动态链接库等。 ??这最后一步就需要链接来完成了。链接时,会将所有的.o文件、动态链接库链接在一起。这时可能会发生找不到动态链接库、找不到定义等错误。注意,如果我们在代码中只对一个函数做了声明,而没有进行定义,那编译时将不会报错,直到链接时找不到函数定义。
gcc常用选项
选项 | 含义 |
---|
-c | 仅对源文件进行编译,不链接生成可执行文件。在对源文件进行查错时,或只需产生目标文件时可以使用该选项。 | -g[gdb] | 在可执行文件中加入调试信息,方便进行程序的调试。如果使用中括号中的选项,表示加入gdb扩展的调试信息,方便使用gdb来进行调试。 | -O[0、1、2、3] | 对生成的代码使用优化,中括号中的部分为优化级别,缺省的情况为2级优化,0为不进行优化。注意,采用更高级的优化并不一定得到效率更高的代码。 | -Dname[=definition] | 将名为name的宏定义为definition,如果括号中的部分缺省,则宏被定义为1. | -Idir | 在编译源程序时增加一个搜索头文件的额外目录dir,即include增加一个搜索的额外目录。 | -Ldir | 在编译源文件时增加一个搜索库文件的目录dir。 | -llibrary | 在编译链接文件时增加一个额外的库,库名为liblibrary.so。 | -w | 禁止所有警告。 | -Wwarning | 允许产生warning类型的警告,warning可以是:main、unused等很多取值。最常用的是-Wall,表示产生所有警告。如果warning取值为error,其含义是将所有警告作为错误(error),即出现警告就停止编译。 |
写代码,分拆编译步骤
文件准备:
- ~/make/src/test_gcc/test_gcc.cpp
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
cout<<"test g++"<<endl;
return 0;
}
首先进行预处理操作。
g++ -E test_gcc.cpp>test.ii
??查看一下文件test.ii的内容,我们可以发现的内容被完整的放在了我们写的代码前面。其实test.ii是可以单独编译的,下面我们来编译test.ii。
g++ -S test.ii
??现在生成了.s,可以打开看一下生成的汇编代码,学过汇编的同学还可以看懂一部分,下一步汇编结束后生成的二进制文件就看不懂了。下面继续进行汇编。 ??前面两步只是做个实验,演示一下编译的具体细节。下面的汇编是要写在makefile里的重点内容。
g++ -c test.s
??这一步不仅可以做汇编操作,还可以一次完成前三步操作。完成后生成test.o。test.o就是由0和1组成的机器指令了。现在还不能执行,还需要最后一步链接。
g++ test.o -o test
./test
总结
- g++ -E test.cpp>test.ii #1.预处理
- g++ -S test.ii #2.编译
- g++ -c test.s #3.汇编
- g++ test.o -o test #4.链接
- ./test #5.运行
|