"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
,这似乎是导致问题的依赖性。
使用:
- 最新的 Rust(1.43.1 通过
rustup
)
arm-unknown-linux-musleabihf
目标
- 最新的
musl-cross-make
和TARGET=arm-linux-musleabihf
- 将
TARGET_CC_linux_arm-unknown-linux-musleabihf
和 CARGO_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...
链接器似乎难以解析特定于 musl 的 time64
符号,原因尚不清楚。
这在以下情况下工作正常:
- 我在 rust 和
musl-cross-make
上都使用 x86_64-linux-musl
目标
- 我用
MUSL_VER=1.1.24
构建 musl-cross-make
我还编写了一个同时使用 time
和 stat
的小 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。
我正在尝试为 arm-linux-musleabihf
交叉编译一个 Rust 项目,但在使用 musl-cross-make
时遇到链接器错误。 Rust 项目依赖于 libgit2
,这似乎是导致问题的依赖性。
使用:
- 最新的 Rust(1.43.1 通过
rustup
) arm-unknown-linux-musleabihf
目标- 最新的
musl-cross-make
和TARGET=arm-linux-musleabihf
- 将
TARGET_CC_linux_arm-unknown-linux-musleabihf
和CARGO_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...
链接器似乎难以解析特定于 musl 的 time64
符号,原因尚不清楚。
这在以下情况下工作正常:
- 我在 rust 和
musl-cross-make
上都使用 - 我用
MUSL_VER=1.1.24
构建
x86_64-linux-musl
目标
musl-cross-make
我还编写了一个同时使用 time
和 stat
的小 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。