在 musl 1.2.0 上交叉编译 rust 项目时“未定义对`__stat_time64'的引用”

gro*_*wse 8 arm cross-compiling rust musl

我正在尝试交叉编译一个 Rust 项目,arm-linux-musleabihf并且在使用musl-cross-make. rust 项目依赖于libgit2,这似乎是导致问题的依赖。

使用:

  • 最新的锈(1.43.1 通过rustup
  • arm-unknown-linux-musleabihf目标
  • 最新musl-cross-makeTARGET=arm-linux-musleabihf
  • 指向TARGET_CC_linux_arm-unknown-linux-musleabihfCARGO_TARGET_ARM_UNKNOWN_LINUX_MUSLEABIHF_LINKER/opt/musl-cross-make/output/bin/arm-linux-musleabihf-gcc

构建时出现错误:

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...
Run Code Online (Sandbox Code Playgroud)

看起来链接器在解析特定于 musl 的time64符号时遇到了困难,目前尚不清楚原因。

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

  • x86_64-linux-musl在锈和musl-cross-make
  • musl-cross-makeMUSL_VER=1.1.24

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

这里发生了什么?libgit2这意味着它找不到正确的__time64符号有什么特别之处?

小智 5

问题是 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)。

然而,当鲁斯特是连接它使用MUSL的版本最终应用程序的libc具有防锈运为x86_64的Linux的-MUSL目标,其中不包括新的time_t的支持,并且没有__stat_time64__time64等于是链接失败。

现在你有两个选择:

  • 使用 musl-cross-make 构建 1.1.24 的 MUSL lib。我不是 100% 知道 Rust 1.44 包含什么版本。它可能是 1.1.22,虽然从我自己的测试中我发现 1.1.24 工作得很好(就像你一样)。
  • 使用您自己的 MUSL libc 版本构建您自己的 Rust 版本和/或目标 liblibc.rlib。我自己从来没有成功地实现过这一点,尽管如果你想尝试这个,可能是一个很好的起点。

正在解决使用 Rust 附带的 libc 而不是本地提供的版本的一般问题,例如这里