Linux编译过程
1.安装gcc,g++
在终端输入以下命令:
sudo apt install gcc
sudo apt install g++
就本质而言,gcc和g++并不是编译器,也不是编译器的集合,它们只是一种驱动器,根据参数中要编译的文件类型,调用对应的GUN编译而已。
更准确的说法:gcc调用了C编译器,而g++调用了C++编译器。
gcc和g++的主要区别
1)对于 *.c和*.cpp文件,gcc分别当做c和cpp文件编译(c和cpp的语法强度是不一样的);
2) 对于 *.c和*.cpp文件,g++则统一当做cpp文件编译;
3)使用g++编译文件时,g++会自动链接标准库STL,而gcc不会自动链接STL;
4)gcc在编译C文件时,可使用的预定义宏是比较少的;
5)gcc在编译cpp文件时或者g++在编译c文件和cpp文件时(这时候gcc和g++调用的都是cpp文件的编译器),会加入一些额外的宏,这些宏如下:
#define __GXX_WEAK__ 1
#define __cplusplus 1
#define __DEPRECATED 1
#define __GNUG__ 4
#define __EXCEPTIONS 1
#define __private_extern__ extern
6)在用gcc编译c++文件时,为了能够使用STL,需要加参数 –lstdc++ ,但这并不代表 gcc –lstdc++ 和 g++等价,它们的区别不仅仅是这个,主要参数:
-g - turn on debugging (so GDB gives morefriendly output)
-Wall - turns on most warnings
-O or -O2 - turn on optimizations
-o - name of the output file
-c - output an object file (.o)
-I - specify an includedirectory
-L - specify a libdirectory
-l - link with librarylib.a
注意:gcc可以编译c++文件
gcc -o mainc++ mainc++.cpp -lstdc++(指明用c++的标准库)
2.编译链接的四步
启动进程:路径+可执行文件名
可以把可执行文件放到 /usr/bin 就可以省略路径了
(1)预编译:
gcc -E main.c -o main.i
(2)编译
gcc -S main.i -o main.s
(3)汇编
gcc -c main.s -o main.o
(4)链接
gcc main.o -o main
执行: ./main
或者:全路径/main
(5)一步执行,省略中间过程
1)三步合为一步
即不经过预编译,编译,汇编三步,直接一步生成.o文件
gcc -c main.c -o main.o
gcc -o main main.o
2)四步合一步
跳过中间部分从main.c到main语句:
gcc -o main main.c
(6)多个源文件执行
1)两步两步:
gcc -c main.c
gcc -c add.c
gcc -c max.
gcc -o main main.o add.o max.o
2)一步完成
gcc -o main main.c add.c max.c
3.编译链接过程
main.c 通过预编译 生成main.i文件
main.i 通过编译生成main.s 文件
main.s 通过汇编生成main.o 文件
链接阶段:将所有的.o .a(静态库文件) .lib(库文件) .obj文件链接起来,生成.out文件 ELF格式的可执行文件 .out文件(Windows生成的是.ext文件)
4.各阶段执行过程
(1)预编译阶段:
1)删除所有的"#define",并且展开所有的宏定义;
2)处理所有的条件预编译指令,"#if","#ifdef","#endif"等;
3)处理"#include"预编译指令,将被包含的文件插入到该预编译指令的位置;
4)删除所有的注释;
5)添加行号和文件名标识,以便于编译器产生调试用的符号信息及编译时产生编译错 误和警告时显示行号;
6)保留所有的#pragma编译器指令,因为编译器需要使用它们;
(2)编译阶段
词法分析,语法分析,语意分析,代码优化,汇总符号;
(3)汇编阶段
将汇编指令翻译成二进制格式,生成各个section,生成符号表
(4)链接阶段
1)合并各个section,调整section的起始位置和段大小,合并符号表,进行符号解析,给符 号分配虚拟地址;
2)符号重定位,即在使用符号的地方全部替换成符号的虚拟地址;