我正在阅读Linux From Scratch 11.0 这本书。在III. 构建 LFS 跨工具链和临时工具,ii。Toolchain Technical Notes,有一点关于加拿大交叉编译的内容。我不明白为什么需要 3 个阶段和 3 台机器才能达到最终结果。本文假设我们从计算机 A 和一个在 A 上运行并为 A 生成二进制文件的编译器开始。那么为什么我们不直接使用该编译器来构建一个在 C 上运行并为 C 构建二进制文件的编译器呢?为什么会有这么多麻烦,构建一个在 A 上运行但为 B 构建的编译器,然后是在 B 上运行但为 C 构建的编译器,最后是在 C 上运行并为 C 构建的编译器?
我还在 Wikipedia 上找到了一篇关于它的文章 - https://en.wikipedia.org/wiki/Cross_compiler。
描述的场景是这样的
您可以在 A 上为 C 构建所有二进制文件,但这需要很长时间,因为机器 A 很慢。
作者认为,在 A 上交叉编译 B 的编译器是值得的。然后可以使用快速机器 B 交叉编译慢速机器 C 的所有必要二进制文件,从而导致总时间避免在 A 或 C 上编译。
最后一步,在 C 上为 C 构建编译器,就是简单地删除对机器 B 的依赖。虽然速度很慢,但机器 C 现在可以直接编译偶尔出现的程序本身。
首先,计算机 C 不是你可以实际编译的东西。它可能是嵌入式设备,甚至只是您不想设置用于编译的生产机器。
所以你有这样一台'nix机器。你需要能够交叉编译它。
你所拥有的是一台构建机器。这是B。它是一台足够快、足够强大的机器,但它没有编译器。它甚至没有为 B 构建的编译器,更不用说为 C 构建的编译器了。你想用它为 C 构建东西。
你怎么得到它?好吧,您与拥有 B 编译器的人交谈,最好是直接交叉编译为 C 的编译器。然后将其下载到 B,并使用它为您的定制系统 C 进行交叉编译。
他们从哪里获得 B 的编译器?很可能他们的系统与 B 不同。他们是如何开始的?
他们真正需要的只是一个系统 A,它带有一个为 A 编译程序的编译器。
现在,已经安装在 A 上的这个编译器可能无法构建交叉编译器。它只是供应商或其他东西提供的语言(如c )的一些编译器。
您需要的是一个可以为 B 编译二进制文件的交叉编译器。为此,首先将 A 带到 A 编译器(您的“供应商”编译器),然后编译一个支持交叉编译到 B 的编译器。
接下来,你使用那个编译器,你让它编译一个从 B 编译到 C 的交叉编译器。
然后,您将该B 到 C 编译器分发给拥有计算机 B 和 C 的人。
...
现在,这是(并且曾经是)一个现实世界的问题。您有一台带有供应商编译器的 microsoft windows 机器、solaris unix 机器或 macOS 机器。在所有情况下,您都可以轻松获得编译器,但不能获得交叉编译器。这些供应商对为您提供交叉编译器几乎没有兴趣。
您没有向您提供工具的每个人都拥有的计算机(B 和 C)。因此,您从“锁定”系统 A 引导到能够构建和分发全套预构建工具供用户下载。
“硬”要求是计算机 A 有一个编译器,可以将 B 到 C 的交叉编译器编译;其中编译器的执行指令集和编译器的目标指令集对 A 都是陌生的。
Roaima 的回答描述了 LFS 提出的逻辑。我不相信 LFS 对“Canadian Cross”的三种编译方式给出了很好的解释。
假设机器 A 为机器 B 生成编译器,该编译器为机器 C 编译:
由于机器 C 的限制,B 和 C 通常不同(是的)。例如,开发人员可能想要为机器 C 编译代码,但 C 是一个非常有限的SBC或嵌入式设备,由于 CPU 和内存限制,不能轻易运行它自己的编译器。因此,开发人员使用他们功能更强大的桌面(机器 B)为 C 编译。
A 和 B 通常是不同的,但不是因为资源限制。更常见的原因通常是编译编译器本身的开发人员与为 C 编译最终代码的开发人员不同。他们通常不在同一个组织中。
例子
拿 ubuntu 包gcc-arm-linux-gnueabihf。这是由 Ubuntu 核心开发人员维护的。任何希望在另一台机器(例如 AMD64 机器)上为 ARM 编译程序的人都可以下载此软件包。也就是说,任何人都可以将它安装到 B 上为 C 编译,而 Ubuntu Core 开发人员无法控制机器的 B 和 C。
现在 Ubuntu Core Developers 编译 gcc-arm-linux-gnueabihf 以在 amd64 arm64 和 i386 上运行。他们不想要或不需要三台构建机器来构建它的所有三个版本。这是因为机器 A可以是与机器 B 和 C 不同的架构。