引导跨平台编译器

时间:2013-02-04 14:45:44

标签: c compiler-construction bootstrapping

假设您正在为一种名为Foo的新语言设计和编写编译器,其优点之一是它对于实现编译器特别有用。一种经典的方法是在C中编写第一个版本的编译器,并使用它在Foo中编写第二个版本,之后它就会自编译。

这意味着您必须小心保留二进制文件的备份副本(而不是大多数只需要保留源代码备份副本的程序);一旦语言从第一个版本演变而来,如果丢失了二进制文件的所有副本,则没有能力编译当前版本。就这样吧。

但是假设它旨在支持Linux和Windows。只要它实际上在两个平台上运行,它就可以在每个平台上自行编译,没问题。假设您在一个平台上丢失了二进制文件(或者有理由怀疑它已被攻击者攻陷);现在有一个问题。并且必须为每个支持的平台保护二进制文件至少还有一个比我更熟悉的失败点。

一种解决方案是使其成为交叉编译器,以便任一平台上的二进制文件都可以针对两个平台。

这并不像听起来那么容易 - 虽然选择二进制输出格式没有问题,但每个平台都以C头文件的形式提供系统API,这些文件通常只存在于其本机平台上,例如:即使编译成Linux二进制格式,也无法保证针对Windows stdio.h编译的代码可以在Linux上运行。

也许这个问题可以通过将Linux头文件下载到Windows机器上并使用Windows二进制文件交叉编译Linux二进制文件来解决。

我是否遗漏了解决方案?

另一种解决方案可能是在Python中维护一个单独的最小引导程序编译器,它将Foo编译为可移植C,只接受主Foo编译器所需的语言子集并执行最小错误检查而不进行优化,意图是因此,引导编译器将保持足够简单,以便在后续语言版本中维护它不会花费太多。

同样,我有什么警告可以解决这个问题吗?

过去人们用什么方法来解决这个问题?

1 个答案:

答案 0 :(得分:3)

这对C编译器本身来说是一个问题。它通常通过使用交叉编译器来解决,正如您所建议的那样。

交叉编译编译器的过程并不比交叉编译任何其他项目困难:也就是说,它比你想要的更棘手,但绝不是不可能的。

当然,您首先需要交叉编译器本身。这可能意味着对构建配置系统进行了一些重大手术,并且您需要从目标中获取某种“sysroot”(标头,库,以及您需要在构建中引用的任何其他内容)。

因此,最终它取决于编译器的结构。要么使用历史源重新引导更容易,重复首先要经历的语言兼容性的每个阶段(你确实使用了源代码修订控制,对吗?),或者更容易实现交叉编译器配置。我无法从这里告诉你。

多年来,GCC编译器总是只在标准兼容的C代码中编写,正是出于这个原因:他们希望能够在任何操作系统上实现它,只给出该系统的本机C编译器。仅在2012年才决定C ++现在已经足够普及,编译器本身就可以用它来编写。即便如此,他们只允许自己成为语言的一个子集。将来,如果有人想将GCC移植到一个还没有C ++的平台上,他们将需要使用交叉编译器,或者第一个端口GCC 4.7(最后一个主要的C-only版本)然后移动到最新版本

此外,GCC构建过程不“信任”它构建的编译器。当您键入“make”时,它首先构建自身的简化版本,然后使用该构建完整版本。最后,它使用完整版本来重建另一个完整版本,并比较两个二进制文件。如果两者不匹配,它知道原始编译器是错误的并且引入了一些错误代码,并且构建失败了。