当将Rust静态库与嵌入式C程序链接时,出现“multiple definition of `memcmp”错误。

6
我是一名有用的助手,可以为您翻译文本。
我有一个 Rust 函数想要从运行在 STM32F412 微控制器上的 C 项目 中调用,但我得到了一系列“多重定义”的链接错误。
这是我的 lib.rs:
#![crate_type = "staticlib"]
#![feature(lang_items)]
#![no_std]
#![no_builtins]

#[no_mangle]
pub extern "C" fn hello_world(a: i32, b: i32) -> i32 {
    a + b
}

#[lang = "eh_personality"] extern fn eh_personality() {}
#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} }

使用 cargo build --release --target=thumbv7em-none-eabihf 构建会生成 librust.a,我将其作为对象添加到了 C 语言的 Makefile 中。

完整的链接错误列表可以在这里找到。使用 nm 命令可以将所有冲突的函数显示为全局文本符号 (T),输出结果在此处

C 语言项目没有标准的 C 库,而是使用自定义的 libc,它是特定设备上的实现,并覆盖了标准库的一小部分。我能告诉 Rust 库使用这些函数吗?

通过阅读 Rust 功能列表,发现有 #![feature(compiler_builtins_lib)],但这恰恰与我想要的相反,因为它会导致出现 "undefined reference to" 链接错误。


1
你能发布 nm librust.a 和你的 Cargo.toml 吗?你是如何链接你的程序的? - Stargateur
我已经添加了nm的输出,我的Cargo.toml除了"crate-type = ["staticlib"]"之外默认设置。arm-none-eabi-ld是链接器,使用普通的Makefile。flags在这里 - Ferdia McKeogh
你能分享一下完整的链接命令行吗?同时尝试在链接时交换你的代码和 Rust 静态库的顺序。 - Shepmaster
1个回答

4

您的自定义“标准库”liba和生成的内置符号插入到librust.a中,导致出现大量重复的符号:

memset, memcpy, memmove, ecc, ecc

你的问题是由于连接时目标文件的顺序问题而引起的。
如果你把`librust.a`放在链接文件序列的前面,那么在它之前的文件将会从`librust.a`中解析符号,在它之后的文件将会从`liba`中解析相同的符号,这会产生重复的符号错误。
为了避免这个问题,把Rust库放在链接对象文件的最后。
在epsilon的Makefile中,更改链接命令为:
RUST_LIB_DIR = <path_to_librust.a>

.SECONDARY: $(objs)
%.$(EXE):
    @echo "LD      $@"
    $(Q) $(LD) $^ $(LDFLAGS) -L$(RUST_LIB_DIR) -l:librust.a -o $@ 

这个配方在我的设备上成功地连接了。 我的基本 epsilon/apps/main.cpp 工具包:

#include "global_preferences.h"
#include "apps_container_storage.h"

extern "C" int hello_world(int a, int b);

void ion_main(int argc, char * argv[]) {

  hello_world(1,2);
  ...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接