"undefined reference to `__stat_time64'" 在 musl 1.2.0 上交叉编译 rust 项目时

"undefined reference to `__stat_time64'" when cross-compiling rust project on musl 1.2.0

我正在尝试为 arm-linux-musleabihf 交叉编译一个 Rust 项目,但在使用 musl-cross-make 时遇到链接器错误。 Rust 项目依赖于 libgit2,这似乎是导致问题的依赖性。

使用:

构建时出现错误:

error: linking with `/opt/musl-cross-make/output/bin/arm-linux-musleabihf-gcc` failed: exit code: 1
...
  = note: /opt/musl-cross-make/output/bin/../lib/gcc/arm-linux-musleabihf/9.2.0/../../../../arm-linux-musleabihf/bin/ld: /tmp/rustcvSvGAJ/liblibgit2_sys-e56c2f9bd024a0a9.rlib(odb.o): in function `git_odb__add_default_backends':
          odb.c:(.text.git_odb__add_default_backends+0x24): undefined reference to `__stat_time64'
          /opt/musl-cross-make/output/bin/../lib/gcc/arm-linux-musleabihf/9.2.0/../../../../arm-linux-musleabihf/bin/ld: /tmp/rustcvSvGAJ/liblibgit2_sys-e56c2f9bd024a0a9.rlib(config.o): in function `git_config_add_file_ondisk':
          config.c:(.text.git_config_add_file_ondisk+0x34): undefined reference to `__stat_time64'
          /opt/musl-cross-make/output/bin/../lib/gcc/arm-linux-musleabihf/9.2.0/../../../../arm-linux-musleabihf/bin/ld: /tmp/rustcvSvGAJ/liblibgit2_sys-e56c2f9bd024a0a9.rlib(config_file.o): in function `config_file_read':
          config_file.c:(.text.config_file_read+0x48): undefined reference to `__stat_time64'
...etc...

链接器似乎难以解析特定于 musl 的 time64 符号,原因尚不清楚。

这在以下情况下工作正常:

我还编写了一个同时使用 timestat 的小 C 程序,它在交叉编译器上构建在 musl 1.2.0 上没有任何问题。

这是怎么回事? libgit2 有什么特别之处,这意味着它找不到正确的 __time64 符号?

您可以尝试 https://github.com/richfelker/libcompat_time32 中列出的说明:

Add -Wl,--whole-archive -lcompat_time32 -Wl,--no-whole-archive to the link command line. Special hacks (like prepending -Wl, to -lcompat_time32) may be needed if libtool is intercepting and mangling the command line.

问题是 Rust 1.44 及以下版本附带的 MUSL libc 是基于 MUSL libc 1.1.X,而不是 1.2.0.

Rust 在构建 libgit2 时也需要构建 libgit2-sys,这是 C 代码。在构建 libgit2-sys 时,它使用你自己构建并使用 musl-cross-make 安装的 MUSL libc 版本。默认情况下是 1.2.0,它重新设计了 time_t 32/64 位支持,依赖于 __stat_time64 和其他各种类似命名的方法(例如 __time64)。

然而,当 Rust link 正在使用你的最终应用程序时,它使用的是 Rust 附带的 MUSL libc 版本用于 x86_64-linux-musl 目标,它不包括新的 time_t 支持,但没有 __stat_time64__time64 等。因此 link 失败。

现在你有两个选择:

  • 使用 musl-cross-make 构建 1.1.24 的 MUSL 库。我不是 100% 知道 Rust 1.44 包含什么版本。它可能是 1.1.22,尽管根据我自己的测试我发现 1.1.24 工作正常(你也是)。
  • 使用您自己的 MUSL libc 版本构建您自己的 Rust 版本 and/or 目标 liblibc.rlib。我自己从未设法成功实现这一目标,但如果您想尝试这个,this 可能是一个不错的起点。

正在处理使用 Rust 附带的 libc 而不是本地提供的版本的一般问题,例如here.

我建议尝试一下 https://github.com/rust-embedded/cross:它在 docker 中设置了交叉编译环境并且可以无缝工作,即使对于此处突出显示的案例也是如此。

AFAICT,他们用正确的版本重新编译了 musl。