【问题标题】:Why is building a cross-compiler harder than building a regular compiler?为什么构建交叉编译器比构建常规编译器更难?
【发布时间】:2010-10-08 03:48:43
【问题描述】:

我所阅读的所有内容似乎都暗示构建交叉编译器比构建针对其运行平台的编译器要困难得多。这是真的?如果是这样,为什么?似乎为任意平台生成汇编代码和系统调用不应该比为运行编译器的平台生成这样的代码和系统调用更难,但也许我只是天真。

【问题讨论】:

  • 构建是指“编程”还是“编译”?
  • 对您所读的内容感兴趣。这是错误的:-)
  • @dsimcha 不,不是明显更难,虽然根据常识可能会稍微更难,但我仍然不完全明白你的意思试图问。

标签: compiler-construction cross-platform cross-compiling


【解决方案1】:

这不一定更难,但可能取决于编译器架构。

编译器不仅将源代码翻译成 asm 和系统调用。它还将预先存在的帮助代码集成到生成的文件中。这是代码,包括启动代码、函数前导码、可以内联的部分 C api 等。

在平台 A 上构建的平台 A 的普通编译器 C1 中,原始编译器 C0 可以直接构建 C1 及其帮助代码(对于 A,因为 C0 以 A 为目标)。

在基于平台 A 的平台 B 的交叉编译器 C2 中,原始编译器 C0 必须首先构建一个不需要 帮助代码的特殊版本的 C2(因为 帮助code 是针对 B 的,而 C0 是针对 A),那么它必须运行 C2 来生成 helper code。根据编译器的不同,它可能需要生成第二个版本的 C2,其中包含 帮助代码。

在没有帮助代码的情况下构建 C2 的受限版本的行为是引导。

【讨论】:

    【解决方案2】:

    以下是我在使用 GCC 交叉编译时遇到的一些问题:

    • 您必须让目标系统中的一些系统文件出现在主机系统上(即 sysroot)才能链接。

    • 某些语言要求在编译时而不是在运行时评估事物;此外,一些优化导致在编译时评估将(在未优化的情况下)在运行时评估的东西。当目标具有主机系统上不存在的数字类型时,在编译时和运行时情况下获得相同的答案可能会很棘手。

    • 测试可能有点烦人。您必须有两个系统,以及一种将程序从一个转移到另一个的方法。

    不过,我遇到的一般问题就是这样。

    【讨论】:

      【解决方案3】:

      “构建交叉编译器比构建针对其运行平台的编译器要困难得多。”

      由于库的构建和访问方式而存在问题。

      在正常情况下,所有库都位于特定位置,并由该系统上的所有应用程序使用。所有构建机制和软件都假定库的位置。 make 文件、编译器等取决于他们可以去特定地点并找到所需内容的想法。

      但是,在交叉编译的情况下,交叉编译器、make 文件等无法做出这些假设 - 如果他们这样做,它们将链接错误的库。

      因此,这实际上归结为开发人员在早期就做出了某些假设,而我们一直坚持这一点。

      在构建根文件系统时会变得更加困难,因为 unix 只知道一个根文件系统。当你构建另一个根文件系统时,你必须创建一个特殊的环境,允许你在不影响真正的根文件系统的情况下对其进行操作。

      -亚当

      【讨论】:

        【解决方案4】:

        您是否有可能正在查看诸如“将 GCC 构建为交叉编译器”之类的特定案例,其中“构建”的意思是“编译”而不是“编写”?

        由于库周围的问题,这可能会更难 - 对于交叉编译器,您需要目标平台的库。对于“本机”(即非交叉)编译器,您显然已经有了目标库。

        在“创建代码生成器”方面,我同意你的看法——或者至少受目标处理器架构的影响比受编译器执行位置的影响更大。

        在某些情况下,交叉编译器比非交叉编译器更容易。我认为一个 8051 托管的 C++ 编译器将是一项艰苦的工作,无论它面向什么平台。

        【讨论】:

          【解决方案5】:

          许多交叉编译器有多个目标。我认为总的来说,多目标编译器比单目标编译器要困难得多,并且所有多目标编译器都是定义交叉编译器。因此很多交叉编译器比非交叉编译器复杂得多。

          在平台 A 上编写只为平台 B 编译代码的编译器原则上不应该比在平台 A 上编写只为平台 A 编译的编译器困难。

          【讨论】:

          • 这是有缺陷的逻辑,因为它不是逻辑,因为它以“我认为”开头。没有解释为什么多目标编译器也更难。
          • 我认为这很明显......您需要多个二值化器,每个目标一个。您还需要确保以一种不仅适用于一个指令集而且可能适用于多个非常不同的指令集的方式在内部表示数据。
          • 针对另一个平台的编译器只需要处理它所针对的一个平台。
          【解决方案6】:

          只有当您从未想过您可能想要进行交叉编译时,才能构建一个交叉编译器。有趣的是,汇编器、链接器和调试器也是如此。您需要做的就是记住创建一个明确的抽象来表示您对目标机器的了解。

          如需了解设计良好、文档完善的交叉编译器示例,请查看lcc。要了解交叉调试器的设计,有conference paper 和doctoral dissertation。 该代码可能是可下载的;我不确定。

          【讨论】:

            【解决方案7】:

            以下问题的答案可能会帮助您理解为什么这会很困难。

            Why can't we create programs cross-platforms these days?

            我觉得这一切都归结为不同的操作系统以不同的方式调用本机 IO。要构建一个独立于平台的编译器,您必须确切了解所有细节是如何工作的,并且基本上是构建一个操作系统。

            [我回家后会更新,因为我现在要下班了]

            【讨论】:

            • 我不同意这一点。如果我有一个可移植的编译器,比如 ansi-C,我可以很容易地在任何有 ansi-c 编译器的平台上编译它。 IO 将如何影响它,它与构建操作系统有什么关系?
            • 除非你在谈论链接/存档,但那是完全不同的球赛。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-04-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-10-16
            • 2011-01-13
            相关资源
            最近更新 更多