g++编译的基本过程
- 预处理
- 编译 –> C to 汇编 –> 汇编 to 机器码
- 链接
如下图所示:
每个阶段的作用如下表:
阶段 | 作用 |
---|---|
预处理 | 宏定义的展开,头文件的包含,以及处理各种编译指令如#progam once等。完成后生成预编译文件 .i |
编译成汇编 | 先调用语法检测对文件的语法进行分析和代码优化,存储分配。通过后生成汇编文件 .s |
编译成机器码 | 生成二进制机器码文件 .o vs中是 .obj |
链接 | 把各种符号的引用转换为可执行文件中的信息,比如要调用函数的位置等。生成可执行文件,linux下可以不用后缀,vs下为 .exe |
注意:在链接步骤才会明确各个函数的调用关系,如果某函数只声明了并没有实现的话,在链接之前是不会报错的
一个例子
现有两个文件main.cpp 和 member.h,在member.h中声明了一个函数void funNone();,下面对比该函数实现了和未实现的编译过程。
代码略
编译脚本
echo "开始生成项目"
ls
echo "清理"
rm out.i out.s out.o out
ls
echo "预处理"
g++ -E main.cpp -o out.i
ls
echo "生成汇编"
g++ -S out.i -o out.s
ls
echo "生成机器码"
g++ -c out.s -o out.o
ls
echo "链接"
g++ out.o -o out
#ld -o out out.o
ls
echo "项目生成完成"
未实现函数,仅声明
wdh@wdh-pc:~/workspace/testC$ sh make.sh
开始生成项目
Debug main.cpp make.sh member.h out out.i out.o out.s Release
清理
Debug main.cpp make.sh member.h Release
预处理
Debug main.cpp make.sh member.h out.i Release
生成汇编
Debug main.cpp make.sh member.h out.i out.s Release
生成机器码
Debug main.cpp make.sh member.h out.i out.o out.s Release
链接
out.o:在函数‘main’中:
main.cpp:(.text+0xf9):对‘funNone()’未定义的引用
collect2: error: ld returned 1 exit status
Debug main.cpp make.sh member.h out.i out.o out.s Release
项目生成完成
在链接的时候报错
已实现,函数的内容是
void funNone(){
out<<123<<endl;
}
开始生成项目
Debug main.cpp make.sh member.h out.i out.o out.s Release
清理
rm: 无法删除'out': 没有那个文件或目录
Debug main.cpp make.sh member.h Release
预处理
Debug main.cpp make.sh member.h out.i Release
生成汇编
Debug main.cpp make.sh member.h out.i out.s Release
生成机器码
Debug main.cpp make.sh member.h out.i out.o out.s Release
链接
Debug main.cpp make.sh member.h out out.i out.o out.s Release
项目生成完成
完美生成,可运行
wdh@wdh-pc:~/workspace/testC$ ./out
123