“"memcmp"的多个定义";将Rust staticlib与嵌入式C程序链接时出错 [英] "multiple definition of `memcmp" error when linking Rust staticlib with embedded C program

查看:164
本文介绍了“"memcmp"的多个定义";将Rust staticlib与嵌入式C程序链接时出错的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Rust函数,我想从运行在STM32F412上的 C项目调用MCU,但出现了一系列多个定义的"链接器错误.

这是我的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)],但这与我想要的完全相反,因为如果您收到未定义的引用"链接器错误.

解决方案

您有一堆重复的符号,这些符号来自您自定义的标准库" liba和插入到librust.a:

memset, memcpy, memmove, ecc, ecc

出现问题是因为链接时目标文件的顺序很重要.

如果将librust.a放在要链接的文件的顺序中过早,则librust.a之前的文件将解析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);
  ...
 

I have a Rust function I would like to call from a C project that runs on an STM32F412 MCU, but I am getting a series of "multiple definition of" linker errors.

Here is my 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 {} }

Building with cargo build --release --target=thumbv7em-none-eabihf produces a librust.a which I added as an object to the C Makefile.

The complete list of linker errors can be found here. nm shows all the conflicting functions as global text symbols (T), full output here.

The C project does not have a normal standard C library, instead it uses a custom libc a device-specific implementation that covers a small portion of the standard. Can I tell the Rust library to use those functions?

Reading through the Rust features list, there is #![feature(compiler_builtins_lib)] but this does the exact opposite of what I want, for if you are getting "undefined reference to" linker errors.

解决方案

You have a bunch of duplicated symbols coming from your customized "standard library" liba and from generated builtin symbols inserted into librust.a:

memset, memcpy, memmove, ecc, ecc

Your problem arises because the order of object files matters when linking.

If you put librust.a too early in the ordered sequence of files to link, then files before librust.a will resolve symbols from librust.a and files coming after librust.a will resolve the same symbols from liba and this generates duplicate symbol errors.

To avoid this problem, put the Rust library at the end of object files to link.

In epsilon Makefile change the link commands as:

RUST_LIB_DIR = <path_to_librust.a>

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

This recipe links successfully on my side. My basic epsilon/apps/main.cpp instrumentation:

#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);
  ...

这篇关于“"memcmp"的多个定义";将Rust staticlib与嵌入式C程序链接时出错的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆