Gcc编译器背后的故事
引言:每个成功的软件程序背后都有一个强大的工具,它将代码变为现实——GCC编译器。从它的起初谦逊到如今成为全球使用最广泛和具有影响力的编译器之一,GCC编译器的故事充满了创新、合作和对卓越的不懈追求。让我们一起深入探索这个令人着迷的旅程,了解这个非凡软件是如何诞生的,以及那些塑造了我们今天构建和运行程序方式的未被讲述的故事。
文章目录
一、GCC 简介
GCC(GNU C Compiler)原名GNU C语言编译器,是由GNU开发的编程语言译器,只能处理C语言。但其很快扩展,变得可处理C++,后来又扩展为能够支持更多编程语言,如Fortran、Pascal、Objective -C、Java、Ada、Go以及各类处理器架构上的汇编语言等,所以改名GNU编译器套件(GNU Compiler Collection)。GCC 编译器是 Linux 系统下最常用的 C/C++ 编译器,大部分 Linux 发行版中都会默认安装。GCC 编译器通常以gcc命令的形式在终端(Shell)中使用.对于要学习Linux的朋友来说,可以在Windows上做一个过渡。
二、Binutils大家族
GNU Binutils是一系列二进制工具的集合。主要包括:
- ld —— GNU链接器
- as—— GNU汇编器
但也包括以下二进制工具:
- addr2line:从目标文件的虚拟地址获取文件的行号或符号。
- ar:可以对静态库做创建、修改和提取的操作。
- c++filt:反编译(反混淆,demangle)C++符号的工具。
- dlltool:创建创建Windows动态库。
- gold:另一种新的、更快的仅支持ELF的链接器。
- gprof:性能分析(profiling)工具程序。
- nlmconv:可以转换成NetWare Loadable Module(NLM)目标文件格式。
- nm:显示目标文件内的符号信息。
- objcopy:复制和转译目标文件。
- objdump:显示目标文件的相关信息,亦可反汇编。
- ranlib:产生静态库的索引。(和
nm -s
功能类似) - readelf: 显示ELF文件的内容。
- size:列出目标文件或库文件的section大小。
- strings:列出文件中可打印的字符串信息。
- strip:从目标文件中移除符号信息。
- windmc:Windows消息资源编译器。
- windres:Windows资源文件编译器。
三、编译实例
main.c文件的编译运行过程
// main.c 代码
#include <stdio.h>
int main()
{
printf("%s","Hello GCC!!!")
}
1 . 预处理(Pre-Processing)
这个阶段主要处理源文件中的#indef、#include和#define预处理命令;
这里主要是把一些include的头文件和一些宏定义,放到源文件中。
-
输入的是C语言的源文件
-
输出 :生成一个中间/预加载文件 *.i(以 .i 结尾的文件)
-
这个阶段对应的gcc命令如下:
#gcc test.c(源文件) -o test.i(将结果生成的文件)
-
说明:它通过对源文件test.c使用E选项来生成中间文件test.i
-
实验代码:gcc -E main.c -o main.i
-
效果图:
2 . 汇编(Assembling)
-
输入:中间文件*.i
-
输出:编译后生成汇编编语言文件*.s
-
这个阶段对应的gcc命令如下:
#gcc -S(汇编) test.i -o test.s(汇编编语言文件) -
说明:它通过对源文件test.c使用S选项来生成汇编文件test.s
-
实验代码:gcc -S main.i -o main.s
-
效果图:
3 . 编译(Compiling)
-
输入文件:汇编文件*.s
-
输出文件:二进制机器代码*.o
-
这个阶段对应的gcc命令如下:
#gcc -c(编译) test.s -o test.o
-
实验代码:gcc -c main.s -o main.o
-
效果图:
在功能上,预处理、编译、汇编是3个不同的阶段
但gcc在实际操作时可以把这3个步骤合并为一个步骤来执行,即使用 -c选项:
- 输入文件:源码*.c文件
- 输出文件:二进制机器代码*.o
- 这个阶段对应的gcc命令如下:
#gcc –c test.c -o test.o
// -o指定了output_filename
或 :
#gcc -c test.c
//省略-o output_filename
//默认输出为test.o
//与源文件同名,后缀为.o
4 . 链接(Linking)
- 输入文件:二进制机器码*.o文件
- 输出文件:与其它的机器代码和库文件汇集成一个可执行的二进制代码文件(无后缀)
- 这个阶段对应的gcc命令如下:
#gcc (没有选项符号) test.o example.o -o test
- 实验代码:gcc main.o -o main
- 效果图:
大佬友情链接
-
https://blog.youkuaiyun.com/weixin_47826078/article/details/120474122
-
https://zhuanlan.zhihu.com/p/561605849
-
https://www.cnblogs.com/tocy/p/gnu-binutils-simple-usage.html