我正在尝试创建一个嵌入友好的可执行文件(占用空间小,不依赖于Rust标准库),它使用已经支持no_std
构建的库(wasmi)。 Rust的新手,我只是拼凑指令,但它的要点似乎是follow the steps。
对于可执行文件:
#![no_std]
#![no_main]
use core::panic::PanicInfo;
/// This function is called on panic.
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
loop {}
}
#[no_mangle]
pub extern "C" fn _start(_argc: isize, _argv: *const *const u8) -> ! {
interpret(_argc, _argv);
loop {}
}
那是为了:
#![no_std]
main
,因为我们没有运行时会调用它)我要编译的Cargo文件如下所示:
[package]
name = "driver"
version = "0.1.0"
edition = "2018"
[dependencies.wasmi]
path = "../../github_dev/wasmi"
features = ["core"]
default-features = false
test=false
bench=false
[profile.release]
panic = "abort"
lto = true
incremental=false
debug=true
opt-level = "z"
test=false
bench=false
并生成一个非常小的二进制文件,排除任何标准库符号(使用nm
检查)并按预期运行。
当我实际尝试从wasmi库调用函数时,会出现问题。它是通过no_std
线与features=core
建造的。对nm
中的文件执行release/deps/libwasmi-*.rlib
不会显示标准库符号。但是,使用此命令进行链接时:
rustc --release --verbose -- -C link-arg=-nostartfiles
它导致:
Compiling driver v0.1.0 (/home/my_home/wasmi_embed/driver)
Running rustc --edition=2018 --crate-name driver src/main.rs --color always --crate-type bin --emit=dep-info,link -C opt-level=3 -C panic=abort -C lto -C link-arg=-nostartfiles -C metadata=957eda2e590447ba -C extra-filename=-957eda2e590447ba --out-dir /home/my_home/wasmi_embed/driver/target/release/deps -L dependency=/home/my_home/wasmi_embed/driver/target/release/deps --extern libc=/home/my_home/wasmi_embed/driver/target/release/deps/liblibc-f7fb773c7b059a14.rlib --extern wasmi=/home/my_home/wasmi_embed/driver/target/release/deps/libwasmi-534aef1926b4eb6c.rlib
并发生错误:
error[E0152]: duplicate lang item found: panic_impl.
--> src/main.rs:31:1
|
31 | / pub extern fn panic(_info: &PanicInfo) -> ! {
32 | | loop {}
33 | | }
| |_^
|
= note: first defined in crate `std`.
看起来Rust似乎试图在标准库支持中链接至少恐慌处理,但我不知道为什么。
我想帮助理解为什么并了解如何防止它。
如果我删除panic_impl
属性然后我的可执行文件编译,但它包括我试图阻止的许多标准库符号。
我看到的示例符号是:
my_home@my_puter:~/wasmi_embed/driver/target/release$ nm --demangle -A -a -B -s --line-number test_2018 2>/dev/null | grep std
driver:00000000000264c0 t rust_begin_unwind /rustc/8e2063d02062ee9f088274690a97826333847e17//src/libstd/panicking.rs:311
driver:00000000000264a0 t rust_oom /rustc/8e2063d02062ee9f088274690a97826333847e17//src/libstd/alloc.rs:203
driver:000000000001f490 t rust_panic /rustc/8e2063d02062ee9f088274690a97826333847e17//src/libstd/panicking.rs:524
driver:0000000000025aa0 t _$LT$std..panicking..continue_panic_fmt..PanicPayload$LT$$u27$a$GT$$u20$as$u20$core..panic..BoxMeUp$GT$::get::he4f810e299a2e0b4 /rustc/8e2063d02062ee9f088274690a97826333847e17//src/libstd/panicking.rs:372
driver:00000000000259a0 t _$LT$std..panicking..continue_panic_fmt..PanicPayload$LT$$u27$a$GT$$u20$as$u20$core..panic..BoxMeUp$GT$::box_me_up::hd8430725259668a8 /rustc/8e2063d02062ee9f088274690a97826333847e17//src/libstd/panicking.rs:367
driver:0000000000021520 t _$LT$std..sys_common..process..DefaultEnvKey$u20$as$u20$core..borrow..Borrow$LT$std..ffi..os_str..OsStr$GT$$GT$::borrow::hbacd0cd7d7fbf1c1/rustc/8e2063d02062ee9f088274690a97826333847e17//src/libstd/sys_common/process.rs:27
driver:0000000000021570 t _$LT$std..error..$LT$impl$u20$core..convert..From$LT$alloc..string..String$GT$$u20$for$u20$alloc..boxed..Box$LT$$LP$dyn$u20$std..error..Err
... plus more
在dep
目录下的任何rlib文件(包括libwasmi)中都找不到上述符号,在不调用libwasmi代码时也未在驱动程序可执行文件中找到它们。
我读过a similar issue(因此我在Cargo.toml中的test=false
和bench=false
),但这没有帮助。我试图用rustc
构建不同的命令(不包括Cargo),但错误是一样的。我已经尝试将wasmi编译为一个静态库(ar)并将其链接进去,但是对于Rust我是新手,我花了很多时间尝试将其链接进去并且它没有发生。
在Rust论坛寻求帮助后我解决了这个问题。 enter link description here。具体来说,无法确定是什么导致生锈std lib链接到我的可执行文件...是一个箱子的问题或货物问题或rustc的问题或链接器的问题。我不知道问题出在哪里,但基于类似的错误提交,我认为不知何故正在编译一个箱子以引入std lib意外。原来错误enter link description here没有相关,即使错误消息是相同的。我没有遇到来自不同类型的依赖项(dev-dependencies和build-dependencies)的意外传播的问题。我尝试了所有这些技术来确定std lib中的内容:
这些都没有帮助我确定引入std lib的内容。最终,在Rust论坛上的建议是使用货物检查来完成一个不允许使用std lib的目标。那些在这里列出*
的人:enter link description here只有核心支持。我试过,用--target=thumbv7m-none-eabi
运行并看到:
错误[E0463]:找不到包的箱子 - > /home/jlb6740/github_dev/hashbrown/src/lib.rs:44:1 | 44 | extern crate std as alloc; | ^^^^^^^^^^^^^^^^^^^^^^^^^^找不到包装箱
原来它是hashbrown,它是我的可执行文件的依赖项的依赖项。它默认构建了no_std,但是有一个extern std以不同的名字链接,并被一个名为“nightly”的功能保护。在我努力不建立任何东西而不是no_std时,警卫被禁用了。没有什么我试过提醒我的箱子,直到这个负责。似乎应该有一个更好的方法来获得比货物树提供的更全面的箱子依赖性列表,但更改wasmi货物以确保夜间功能设置解决了我的问题。