这个问题困扰着我一段时间了。GCC和g++是如何编译自己的?
我猜每个修订版本都是用之前构建的版本编译的。这是真的吗?如果是这样,是否意味着最旧的g++和GCC版本是用汇编语言编写的?
这个问题困扰着我一段时间了。GCC和g++是如何编译自己的?
我猜每个修订版本都是用之前构建的版本编译的。这是真的吗?如果是这样,是否意味着最旧的g++和GCC版本是用汇编语言编写的?
最早的GCC版本是使用另一个C编译器进行编译的,因为在它被编写时还有其他编译器可用。第一款C编译器(约1973年左右)可能是用PDP-11汇编语言或其前身B语言实现的,但无论哪种方式,B编译器都是用汇编语言编写的。同样地,第一款C++编译器(CPre/Cfront,1979-1983)可能首先是用C实现的,然后用C++重写。
当你编译GCC或任何自托管编译器时,完整的构建顺序如下:
这个过程称为引导。它测试编译器编译自身的能力,并确保生成的编译器使用了它本身实现的所有优化。
编辑:在评论中,Drew Dormann指向了Bjarne Stroustrup关于C++最早实现的描述。它是用C++实现的,但由Stroustrup称为“预处理器”从C++翻译成C;按他的定义不是一个完整的编译器,但仍然使用C ++引导了C ++。
__DATE__
和 __TIME__
这样即使在同一编译器调用之间也会变化的宏),与使用[GCC compiled with [other]]编译的GCC相同 - 如果不是这样,那就是一个错误,而3阶段引导构建就是为了捕捉这种情况。 - pmdj如果您想在现代环境(x86 Linux)中复制GCC的引导过程,可以使用由bootstrappable项目开发的工具:
我们可以从hex0
汇编器(在x86上是357字节二进制文件)开始,它大致执行以下两个命令所做的操作:
sed 's/[;#].*$//g' hex0_x86.hex0 | xxd -r -p > hex0
chmod +x hex0
即将二进制程序的ASCII等效项翻译成二进制代码,但是它本身是用hex0编写的。
基本上,hex0有与其二进制代码一一对应的等效源代码。
hex0
可用于构建稍微更强大一些的hex1
汇编程序,支持一些其他功能(一个字符标签和计算偏移量)。 hex1是用hex0汇编语言编写的。
hex1
可用于构建hex2
(支持多字符标签的更先进的汇编程序)。
然后可以使用hex2
来构建宏汇编程序(使用宏而不是十六进制操作码的程序)。
然后可以使用该宏汇编程序构建在汇编语言中编写的“C编译器”cc_x86
。cc_x86仅支持C的一小部分,但这是一个令人印象深刻的开端。
您可以使用cc_x86
构建在C中编写的C编译器M2-Planet
(宏平台中性转换器)。M2-Planet是自主主机并且可以构建它自己。
然后可以使用M2-Planet构建小型方案解释器GNU Mes。
mes可用于运行在方案中编写的C编译器mescc,并与mes位于同一存储库中。
mescc可用于重新构建mes并构建mes C库。
然后可以使用mescc构建稍微修复的Tiny C编译器。
然后可以使用它来构建更新版本的TCC 0.9.27。
使用旧版GCC可以构建GCC 4.0.4和musl C库。
然后可以使用旧版GCC构建较新版本的GCC。 例如,GCC 4.0.4-> GCC 4.7.4->现代GCC。
简而言之:
hex0 -> hex1 -> hex2 -> M0 -> M2-Planet -> Mes -> Mescc -> TCC -> GCC。