如何解决为什么货物/ rustc链接锈标准库符号,即使使用no_std?

问题描述 投票:4回答:1

我正在尝试创建一个嵌入友好的可执行文件(占用空间小,不依赖于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,因为我们没有运行时会调用它)
  • 并定义一个恐慌处理程序,因为不包含Rust std lib来为我们定义它。

我要编译的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=falsebench=false),但这没有帮助。我试图用rustc构建不同的命令(不包括Cargo),但错误是一样的。我已经尝试将wasmi编译为一个静态库(ar)并将其链接进去,但是对于Rust我是新手,我花了很多时间尝试将其链接进去并且它没有发生。

rust rust-cargo
1个回答
-1
投票

在Rust论坛寻求帮助后我解决了这个问题。 enter link description here。具体来说,无法确定是什么导致生锈std lib链接到我的可执行文件...是一个箱子的问题或货物问题或rustc的问题或链接器的问题。我不知道问题出在哪里,但基于类似的错误提交,我认为不知何故正在编译一个箱子以引入std lib意外。原来错误enter link description here没有相关,即使错误消息是相同的。我没有遇到来自不同类型的依赖项(dev-dependencies和build-dependencies)的意外传播的问题。我尝试了所有这些技术来确定std lib中的内容:

  1. 我尝试使用货物树列出依赖项列出所有的箱子依赖项: wasmi v0.4.3(/ home / jlb6740 / github_dev / wasmi) ├──字节顺序v1.3.1(/ home / jlb6740 / github_dev / byteorder) ├──puckbrownv0.1.8(/ home / jlb6740 / github_dev / hashbrown) │├──byalorderv1.3.1(/ home / jlb6740 / github_dev / byteorder)() │└──scopeguard v0.3.3(/ home / jlb6740 / github_dev / scopeguard) ├──libmv0.1.2 ├──memory_unitsv0.3.0 └──parent-wasm v0.31.0(/ home / jlb6740 / github_dev / parity-wasm) └──byodeorderv1.3.1(/ home / jlb6740 / github_dev / byteorder)()
  2. 我尝试使用货物rustc --verbose ...但此时详细并未表明任何使用默认功能的内容可能包括使用std
  3. 我尝试使用货物元数据...这产生了一长串难以解析的依赖关系,但我确实看到了一些范围,其中scopeguard和byteorder具有需要std支持的默认功能。我下载了所有这些板条箱和硬编码属性,这样箱子只能用no_std支持构建。
  4. 我试着查看deps / output并在所有rlib上做了一个nm来查看是否有任何库使用了std中的符号。我找不到那种情况。我认为rlibs就像静态库,他们使用的任何东西都会被包含在rlib中,但显然不是。
  5. 我查看货物rustc - -C --print-link-args检查链接器标志,但我找不到任何明显的告诉我它引入了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货物以确保夜间功能设置解决了我的问题。

© www.soinside.com 2019 - 2024. All rights reserved.