linux 编译程序的过程与C/C++程序编译过程类似,只是使用的命令或实现的方法不一样(环境平台不一样),但是总体框架一样。
一、预编译
命令是gcc -E main.c -o main.o 假设当前要编译的文件是main.c;
1、将所有的#define删除,并展开所有的宏定义;
2、处理所有的预编译指令,例如:#if,#elif,#else,#endif;
3、处理#include预编译指令,将被包含的文件插入到预编译指令的位置;
4、添加行号信息文件名标识,便于调试;
5、删除所有的注释;
6、保留所有的#pragma编译指令,因为在编写程序的时候,我们经常要用到#pragma指令来设定编译器的状态或者是指示编译器完成一些特定的动作。
7、生成.i文件。
包括去注释 ,宏替换 ,头文件展开,条件编译,经编译后的.i文件不包含任何宏定义,因为所有的宏已经被展开,并且包含的文件已经被插入到.文件中。
二、编译:C语言——》汇编
命令是:gcc -s main.i -o main.s
1、扫描,语法分析,语义分析,源代码优化,目标代码生成,目标代码优化;
2、生成汇编代码;
3、汇总符号;
4、生成.s文件
三、汇编:汇编——》二进制
命令是:gcc -c main.s -o main.o
1、根据汇编指令和特定平台,把汇编指令翻译成二进制形式;
2、合并各个section,合并符号表;
3、生成.o文件。
四、链接
1、合并各个.obj文件的section,合并符号表,进行符号解析;
2、符号地址重定位;
3、生成可执行文件;
也可以从c源代码开始经过预处理,编译,汇编,链接直接输出可执行文件,他的命令是:gcc -c main.s -o main.o 。
五、总结:
无论是linux系统平台还是其它的系统平台,整体的编译流程几乎都是一样的,整体流程如下图(便于理解)。