如何在 ARM 交叉编译时选择要链接的静态库?

Posted

技术标签:

【中文标题】如何在 ARM 交叉编译时选择要链接的静态库?【英文标题】:How can I select a static library to be linked while ARM cross compiling? 【发布时间】:2014-08-28 06:26:00 【问题描述】:

我在 Ubuntu (arm-linux-gnueabi-gcc) 中有一个 ARM 交叉编译器,默认架构是 ARMv7。但是,我想编译一个 ARMv5 二进制文件。我通过为编译器提供-march=armv5te 选项来做到这一点。

到目前为止,一切都很好。由于我的 ARM 系统使用 BusyBox,我必须编译静态链接的二进制文件。所以我给 gcc -static 选项。

但是,链接器链接到我的 ARMv5 二进制文件的 libc.a 存在问题。该文件是使用 ARMv7 架构选项编译的。所以,即使我用 ARMv5 交叉编译我的 ARM 二进制文件,我也无法在基于 BusyBox 的 ARMv5 机器上运行它。

    我该如何解决这个问题? 我在哪里可以获得 ARMv5 libc.a 静态库,如何链接它?

提前谢谢你。

【问题讨论】:

【参考方案1】:

你有两个选择,

    获取正确的编译器。 编写您自己的“C”库。

获取正确的编译器。

让编译器与您的系统匹配,您总是是最安全的。这适用于 x86 Linux 和各种发行版。如果不同的编译器工作,你很幸运。当您交叉编译时会更加困难,因为编译器不会自动同步。尝试在 2014 Ubuntu 系统上编译的 1999 x86 Mandrake Linux 上运行程序。

除了指令兼容性(您已确定)之外,还有 ABI 和操作系统依赖项。具体来说,armv7 很可能是 hardfloat(具有 浮点 FPU 和寄存器调用约定),您需要一个 softfloat(模拟 FPU)。特定的glibc(或ucLibc)对Linux OS 有特定的调用和期望。例如,threads 的工作方式随着时间的推移发生了变化。

自己写

您始终可以使用-fno-builtin-ffreestanding 以及-static。那么你就不能使用任何libc函数了,但是你可以program them your self.

有外部源,如Mark Martinec's snprintf 和易于实现的构建块如write()

#define _SYS_IOCTL_H 1
#include <linux/unistd.h>
#include <linux/ioctl.h>
static inline int write(int fd, void *buf, int len)

    int rval;
        asm volatile ("mov      r0, %1\n\t"
                "mov    r1, %2\n\t"
                "mov    r2, %3\n\t"
                "mov    r7, %4\n\t"
                "swi    #0\n\t"
                "mov    %0, r0\n\t"
                : "=r" (rval)
                : "r" (fd),
                  "r" (buf),
                  "r" (len),
                  "Ir" (__NR_write)
                : "r0", "r1", "r2", "r7");
    return rval;


static inline void exit(int status)

        asm volatile ("mov      r0, %0\n\t"
                "mov    r7, %1\n\t"
                "swi    #0\n\t"
                : : "r" (status),
                  "Ir" (__NR_exit)
                : "r0", "r7");

您必须添加由“C”库负责的自己的启动机器,

/* Called from assembler startup. */
int main (int argc, char*argv[])

    write(STDOUT, "Hello world\n", sizeof("Hello world\n"));
    return 0;


/* Wrapper for main return code. */
void __attribute__ ((unused)) estart (int argc, char*argv[])

    int rval = main(argc,argv);
    exit(rval);


/* Setup arguments for estart [like main()]. */
void __attribute__ ((naked)) _start (void)

    asm(" sub     lr, lr, lr\n"   /* Clear the link register. */
        " ldr     r0, [sp]\n"     /* Get argc... */
        " add     r1, sp, #4\n"   /* ... and argv ... */
        " b       estart\n"       /* Let's go! */
        );

如果这太令人生畏了,因为您需要实现很多功能,那么您可以尝试获取各种库源并使用-fno-builtin 重新构建它们,并确保这些库不与 Ubuntu 库链接,不兼容。

像crosstool-ng 这样的项目可以让您构建完全适合armv5 系统的正确编译器(可能具有更高级的代码生成)。这可能看起来很痛苦,但上述替代方案也并不容易。

【讨论】:

以上代码适用于 Linux 2.6.36 和 EABI 系统调用 Linux(不是 OABI)。您必须拥有 Linux 头文件才能编写自己的库。 dmesgcat /proc/version 应该告诉你你的 Linux 版本,而不是配置。

以上是关于如何在 ARM 交叉编译时选择要链接的静态库?的主要内容,如果未能解决你的问题,请参考以下文章

如何交叉编译 动态库

cmake:arm-xm-linux交叉编译工具链文件及交叉支持HTTPS的curl静态库

cmake:arm-xm-linux交叉编译工具链文件及交叉支持HTTPS的curl静态库

交叉编译时如何使用外部库?

QT5静态编译工程(arm交叉编译)

arm-linux-gcc交叉编译是静态编译还是动态的