“"memcmp"的多个定义";将Rust staticlib与嵌入式C程序链接时出错 [英] "multiple definition of `memcmp" error when linking Rust staticlib with embedded C program
问题描述
我有一个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屋!