交叉编译或编译Native Arch for CPU Arch

编写依赖于CPU拱的软件时,例如在x86上运行的C代码或在ARM cpus上运行的C代码。 通常有两种方法可以编译这些代码,或者交叉编译到ARM CPU拱门(例如,如果你在x86系统上进行开发),或者将代码复制到本机arch cpu系统并进行天真编译。

我想知道原生方法和交叉编译方法是否有好处? 我注意到Fedora ARM团队正在使用慢速/低功耗ARM设备的构建服务器集群来“天真地”编译他们的Fedora ARM旋转……当然,由Red Hat支持的项目可以访问运行x86 cpu的一些强大的构建服务器这可以在1/2的时间内完成工作……为什么他们选择? 我是否通过交叉编译我的软件而错过了什么?

从技术上讲,你不会在.c – > .o – > a.out(或其他)的上下文中通过交叉编译而遗漏任何东西; 交叉编译器将为您提供与本机编译器相同的二进制文件(尽管版本等)

本地构建的“优势”来自后编译测试和管理复杂系统。

1)如果我可以在编译后快速运行unit testing,我可以快速解决任何错误/问题,周期可能比交叉编译周期短;

2)如果我正在编译一些具有它使用的第三方库的目标软件,那么在本机平台上构建,部署然后使用它们构建我的目标可能会更容易; 我不想处理那些交叉编译的构建,因为其中有一半是由疯狂的猴子编写的构建过程,这使得交叉编译它们很痛苦。

通常对于大多数事情,人们会尝试进入基础构建并本地编译其余的构建。 除非我有一个生病的设置,我的交叉编译器是快速超级恶劣的,我节省时间是值得的设置所需的其他事情(如unit testing和依赖管理)更容易。

至少那些是我的想法

主要的好处是,本机运行时不需要调整所有./configure脚本。 如果您使用的是shadow rootfs ,那么仍然有运行uname配置来检测CPU类型等。例如,请参阅此问题 。 pkgconfig和其他工具试图简化交叉构建 ,但是软件包通常首先在x86上进行本机构建 ,然后在ARM上进行本机构建交叉建设可能会很痛苦,因为每个包都可能需要单独调整。

最后,如果您正在按照Joachim进行配置文件引导优化和运行测试套件 ,那么在交叉构建环境中执行此操作几乎是不可能的。

ARM上的编译速度明显快于人类包构建器 ,读取configure ,编辑configure ,重新运行配置,编译,链接循环。

这也适用于持续集成策略。 可以快速构建/部署/测试各种包,尤其是的测试可能涉及数百个依赖包。 Arm Linux distrubutions通常需要在升级和修补基础库时进行原型更改,基础库可能包含数百个至少需要重新测试的依赖包。 计算机完成的慢速循环总是比快速编译然后手动人工干预更好。

本机编译的唯一好处是您不必将程序转移到目标平台,因为它已经存在。

然而,当考虑到与现代x86 PC相比大多数目标平台的function不足时,这并不是一个很大的好处。 内存量,更快的CPU以及更快的磁盘使得PC上的编译时间快了许多倍。 因此,原生建筑的优势不再是真正的优势。

这在很大程度上取决于编译器。 工具链如何处理本机编译和交叉编译之间的区别。 仅仅是工具链的情况总是认为它是作为交叉编译器构建的,但构建它的一种方法是让configure脚本自动检测主机而不是手动执行(并自动设置前缀等) )?

不要以为它只是因为它是一个原生编译器而构建它真的是原生的。 在许多情况下,发行版使其本机编译器(以及内核和其他二进制文件)愚蠢,以便该发行版在更广泛的系统上运行。 在ARMv6系统上,您可能正在运行默认为ARMv4的编译器。

如果我使用一个默认体系结构构建工具链,然后指定另一个与构建目标体系结构的工具链不同的问题,这就引发了与您自己类似的问题?

理想情况下,无论您是本机还是交叉编译并且独立于默认体系结构,您都希望大多数调试的编译器/工具链能够为您提供相同的结果。 现在我在旧的llvm上看到llvm-gcc在64位主机上运行时,交叉编译到arm将构建所有的int,因为64位为代码增加了很多,相同的编译器版本,32位的相同源代码主机会给出不同的结果(32位整数)。 基本上-m32开关不适用于llvm-gcc(当时),我不知道是否仍然如此,因为我在做llvm工作时切换到clang并且从不回头看llvm-gcc … llvm / clang例如,主要是交叉编译器,链接器是唯一看起来特定于主机的东西,您可以使用现成的llvm并为任何主机系统上的任何目标进行编译(前提是您的构建没有禁用任何目标)当然支持的目标)。