树莓派C++项目链接第三方Rust静态库时遇链接错误求助
问题
我在为树莓派开发的C++项目中链接第三方Rust编写的静态库libkeypad.a时,遇到两个链接错误——编译阶段(库与客户端代码均以树莓派为目标平台)正常,但链接失败:
__sync_fetch_and_add_4符号多重定义:该符号同时存在于libgcc.a和libkeypad.a中,因不熟悉Rust无法修改库代码;posix_spawn_file_actions_addchdir_np未定义引用:查询得知该符号是glibc新增接口,当前使用的glibc版本为2.38-150600.14.37.1。
链接命令及错误详情
arm-unknown-linux-gnueabihf-g++ -std=c++11 -ggdb -Wall -Wextra -Wmultichar -O1 -fstack-protector-all -mfpu=neon -mfloat-abi=hard main.o vfd.o relay.o receiver.o widgets.o tmc.o database.o sound.o ProceduralTimerTaskAdapter.o cd.o TrafficMessage.o keypad.o libkeypad.a -o autoradio -L /import/valen/autoradio:${HOME}/x-tools/arm-unknown-linux-gnueabihf/arm-unknown-linux-gnueabihf/sysroot/usr/lib/arm-linux-gnueabihf:${HOME}/x-tools/arm-unknown-linux-gnueabihf/arm-unknown-linux-gnueabihf/sysroot/lib/arm-linux-gnueabihf:${HOME}/x-tools/arm-unknown-linux-gnueabihf/arm-unknown-linux-gnueabihf/sysroot/usr/lib:/usr/lib -Wl,-rpath-link=/import/valen/autoradio:${HOME}/x-tools/arm-unknown-linux-gnueabihf/arm-unknown-linux-gnueabihf/sysroot/usr/lib/arm-linux-gnueabihf:${HOME}/x-tools/arm-unknown-linux-gnueabihf/arm-unknown-linux-gnueabihf/sysroot/lib/arm-linux-gnueabihf:${HOME}/x-tools/arm-unknown-linux-gnueabihf/arm-unknown-linux-gnueabihf/sysroot/usr/lib -lpthread -lkeystonecomm -lgps -lpigpio -lpigpiod_if2 -lrt -lGeographic -lmk4 -lcsvparser -lasound -lespeak-ng -lmpg123 -lout123 -lPocoFoundation -lPocoUtil -lcdio++ -lcdio -lserial /home/jacek/x-tools/arm-unknown-linux-gnueabihf/lib/gcc/arm-unknown-linux-gnueabihf/8.3.0/../../../../arm-unknown-linux-gnueabihf/bin/ld.bfd: /home/jacek/x-tools/arm-unknown-linux-gnueabihf/lib/gcc/arm-unknown-linux-gnueabihf/8.3.0/libgcc.a(linux-atomic.o): in function `__sync_fetch_and_add_4': /opt/crosstool-ng/.build/arm-unknown-linux-gnueabihf/src/gcc/libgcc/config/arm/linux-atomic.c:65: multiple definition of `__sync_fetch_and_add_4'; libkeypad.a(63f8a0b8a638da8c-sync_fetch_and_add_4.o):/checkout/src/llvm-project/compiler-rt/lib/builtins/arm/sync_fetch_and_add_4.S:19: first defined here /home/jacek/x-tools/arm-unknown-linux-gnueabihf/lib/gcc/arm-unknown-linux-gnueabihf/8.3.0/../../../../arm-unknown-linux-gnueabihf/bin/ld.bfd: libkeypad.a(std-840269a4f33ba77d.std.aa24067b8e80e546-cgu.0.rcgu.o): in function `std::sys::process::unix::unix::<impl std::sys::process::unix::common::Command>::posix_spawn': /rustc/ed61e7d7e242494fb7057f2657300d9e77bb4fcb/library/std/src/sys/process/unix/unix.rs:720: undefined reference to `posix_spawn_file_actions_addchdir_np' collect2: error: ld returned 1 exit status make: *** [Makefile:24: autoradio] Fehler 1
已尝试的方案
曾在库的config.toml中添加Rust编译参数-C link-arg=-Wl,--allow-multiple-definition,但未解决问题。config.toml内容如下:
[build] target = "armv7-unknown-linux-musleabihf" # Workaround for: https://github.com/rust-lang/compiler-builtins/issues/420 rustflags = ["-C", "link-arg=-Wl,--allow-multiple-definition"] [target.armv7-unknown-linux-gnueabihf] runner = "qemu-arm" linker = "arm-linux-gnueabihf-gcc" [target.armv7-unknown-linux-musleabihf] runner = "qemu-arm" linker = "lld"
解决方案
1. 解决__sync_fetch_and_add_4多重定义问题
你之前在Rust的config.toml里加的参数是给Rust编译阶段用的,但实际链接由C编译器触发,因此需要把--allow-multiple-definition直接加到C的链接命令中:
arm-unknown-linux-gnueabihf-g++ ... -Wl,--allow-multiple-definition libkeypad.a ... -o autoradio ...
也可以调整库的链接顺序,把libkeypad.a放在libgcc.a之前,让链接器优先使用库中的符号,但--allow-multiple-definition的方式更直接。
2. 解决posix_spawn_file_actions_addchdir_np未定义问题
该符号是glibc的非标准扩展,问题出在Rust编译时默认依赖了这个高版本glibc接口,有两种解决途径:
方法一:修改Rust编译参数,禁用该符号依赖
更新Rust的config.toml,给目标平台添加rustflags:
[target.armv7-unknown-linux-gnueabihf] rustflags = ["-C", "link-arg=-U_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR_NP"]
或者编译Rust库时临时设置环境变量:
export RUSTFLAGS="-C link-arg=-U_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR_NP" cargo build --target armv7-unknown-linux-gnueabihf --release
方法二:升级glibc(备选)
如果无法修改Rust编译参数,可以尝试升级树莓派系统的glibc版本,使其支持该接口,但这种方法可能涉及系统依赖变更,复杂度较高,优先推荐方法一。
内容的提问来源于stack exchange,提问作者Neppomuk
相关产品推荐
相关产品推荐

