4

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

我想知道本机方法与交叉编译方法相比是否有好处?我注意到 Fedora ARM 团队正在使用一个由慢速/低功耗 ARM 设备组成的构建服务器集群来“天真地”编译他们的 Fedora ARM spin……当然,由 Red Hat 支持的项目可以访问一些运行 x86 cpus 的强大构建服务器这可以在 1/2 的时间内完成工作......那么他们为什么选择呢?我是否因为交叉编译我的软件而遗漏了什么?

4

5 回答 5

4

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

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

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

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

于 2013-05-06T17:57:27.873 回答
2

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

然而,考虑到与现代 x86 PC 相比,大多数目标平台的功能严重不足,这并不是一个很大的好处。内存量、更快的 CPU 和特别是更快的磁盘使 PC 上的编译时间快了很多倍。以至于原生建筑的优势不再是真正的优势。

于 2013-05-06T17:02:34.833 回答
2

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

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

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

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

通常,对于大多数事情,人们会尝试进行基本构建,然后本地编译其余的。除非我有一个病态的设置,我的交叉编译器速度非常快,而且我节省的时间值得进行设置,以使其余的事情(例如单元测试和依赖项管理)更容易。

至少这些是我的想法

于 2013-05-06T17:10:58.480 回答
1

这很大程度上取决于编译器。工具链如何处理原生编译和交叉编译之间的差异。是否只是工具链始终认为它被构建为交叉编译器的一种情况,但是构建它的一种方法是让配置脚本自动检测主机而不是您手动进行(并自动设置前缀等)?

不要假设仅仅因为它被构建为原生编译器,它就真的是原生的。在许多情况下,发行版会降低其本机编译器(以及内核和其他二进制文件),以便该发行版可以在更广泛的系统上运行。例如,在 ARMv6 系统上,您可能正在运行默认为 ARMv4 的编译器。

这引出了一个与您自己类似的问题,如果我使用一个默认架构构建工具链,那么指定另一个与为目标架构构建工具链有什么不同?

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

于 2013-05-06T18:39:26.443 回答
1

尽管很多人认为“本地编译”比“交叉编译”更有好处,或者至少没有区别,但事实恰恰相反。

对于在较低级别(即linux内核)上工作的人,他们通常会遭受编译平台周围的复制。以 x86 和 ARM 为例,直接的想法是构建 ARM 编译库,但这是个坏主意。

二进制有时是不一样的,例如,

# diff hello_x86.ko hello_arm.ko
Binary files hello_x86.ko and hello_arm.ko differ
# diff hello_x86_objdump.txt hello_arm_objdump.txt
2c8
< hello_x86.ko:     file format elf64-littleaarch64
---
> hello_arm.ko:     file format elf64-littleaarch64
26,27c26,27
<    8: 91000000        add     x0, x0, #0x0
<    c: 910003fd        mov     x29, sp
---
>    8: 910003fd        mov     x29, sp
>    c: 91000000        add     x0, x0, #0x0

一般来说,较高级别的应用程序可以同时使用,建议使用较低级别(硬件相关)的工作,x86 "cross compile"因为它具有更好的工具链。

无论如何,编译是关于 GCC Glibc 和 lib.so 的工作,如果熟悉这些,任何一种方式都应该容易上手。

PS:下面是源码

# cat hello.c
#include <linux/module.h>      /* Needed by all modules */
#include <linux/kernel.h>      /* Needed for KERN_ALERT */
#include <linux/init.h>        /* Needed for the macros */



static int hello3_data __initdata = 3;


static int __init hello_3_init(void)
{
   printk(KERN_ALERT "Hello, world %d\n", hello3_data);
   return 0;
}


static void __exit hello_3_exit(void)
{
   printk(KERN_ALERT "Goodbye, world 3\n");
}


module_init(hello_3_init);
module_exit(hello_3_exit);

MODULE_LICENSE("GPL"); 
于 2019-10-31T07:36:05.253 回答