简体   繁体   English

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

[英]How to troubleshoot why cargo/rustc links in rust standard library symbols even when no_std is used?

I am trying to create an embed-friendly executable (small footprint and without dependency on the Rust standard library) that uses a library (wasmi) that already has support for a no_std build. 我正在尝试创建一个嵌入友好的可执行文件(占用空间小而且不依赖于Rust标准库),它使用已经支持no_std构建的库(wasmi)。 New to Rust, I am simply piecing together instructions, but the gist of it appears to be follow the steps . Rust的新手,我只是拼凑指令,但它的要点似乎是按照步骤

For the executable: 对于可执行文件:

#![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 {}
}

That is to: 那是为了:

  • include #![no_std] 包括#![no_std]
  • define our entry (not main since we don't have a runtime that will call it) 定义我们的条目(不是main因为我们没有运行时会调用它)
  • and define a panic handler since the Rust std lib is not included to define it for us. 并定义一个恐慌处理程序,因为不包含Rust std lib来为我们定义它。

My Cargo file to compile this looks like this: 我要编译的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

and produces a very small binary that excludes any standard library symbols (using nm to check) and runs as expected. 并生成一个非常小的二进制文件,排除任何标准库符号(使用nm检查)并按预期运行。

The problem occurs when I actually try to call a function from the wasmi library. 当我实际尝试从wasmi库调用函数时,会出现问题。 It is built with no_std via the features=core line. 它通过features=core line使用no_std构建。 Doing an nm on the files in release/deps/libwasmi-*.rlib shows no standard library symbols. release/deps/libwasmi-*.rlib的文件执行nm release/deps/libwasmi-*.rlib显示标准库符号。 However when linking occurs with this command: 但是,使用此命令进行链接时:

rustc --release --verbose -- -C link-arg=-nostartfiles

it leads to: 它导致:

   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

and an error occurs: 并发生错误:

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`.

It seems Rust is trying to link in standard library support for at least panic handling, but I don't know why. 看起来Rust似乎试图在标准库支持中链接至少恐慌处理,但我不知道为什么。

I would like help to understand why and to understand how to prevent it. 我想帮助理解为什么并了解如何防止它。

If I remove the panic_impl attribute then my executable compiles, but it includes a lot of standard library symbols that I am trying to prevent. 如果我删除panic_impl属性然后我的可执行文件编译,但它包括我试图阻止的许多标准库符号。

The example symbols I see are: 我看到的示例符号是:

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

The above symbols are not found in any of the rlib files under the dep directory including libwasmi, nor are they found in the driver executable when not calling libwasmi code. dep目录下的任何rlib文件(包括libwasmi)中都找不到上述符号,在不调用libwasmi代码时也没有在驱动程序可执行文件中找到它们。

I've read a similar issue (hence my test=false and bench=false in the Cargo.toml) but that did not help. 我已经阅读了类似的问题 (因此我的test=false和在Cargo.toml中的bench=false ),但这没有帮助。 I've tried to build with just rustc with varying commands (excluding Cargo) but the error is the same. 我试图使用不同的命令(不包括货物)生成只有rustc ,但错误是相同的。 I've tried to compile wasmi as a static library (ar) and link it in, but being new to Rust I was spending a lot of time trying to link it in and it just wasn't happening. 我已经尝试将wasmi编译为一个静态库(ar)并将其链接进去,但是对于Rust来说我是新手,我花了很多时间尝试将其链接起来并且它没有发生。

I resolved this after seeking some help in the rust forums. 在Rust论坛寻求帮助后我解决了这个问题。 enter link description here . 在此输入链接描述 Specifically, was not able to determine what was responsible for rust std lib being linked into my executable ... was it an issue with a crate or an issue with cargo or an issue with rustc or an issue with the linker. 具体来说,无法确定是什么导致生锈std lib链接到我的可执行文件...是一个箱子的问题或货物问题或rustc的问题或链接器的问题。 I did not know where the problem was born, but based on similar bugs filed I figured that somehow a crate was being compiled to bring in std lib unexpected. 我不知道问题出在哪里,但基于类似的错误提交,我认为不知何故正在编译一个箱子以引入std lib意外。 Turns out bug enter link description here was not related even though the error message was the same. 原来错误输入链接描述在这里没有关系,即使错误消息是相同的。 I did not have an issue with unexpected propagations form different type of dependencies (dev-dependencies and build-dependencies). 我没有遇到来自不同类型的依赖项(dev-dependencies和build-dependencies)的意外传播的问题。 I tried all these techniques to pinpoint what was bringing in std lib: 我尝试了所有这些技术来确定std lib中的内容:

  1. I tried using cargo tree to list dependencies to list all the crate dependencies: 我尝试使用货物树列出依赖项列出所有的箱子依赖项:

    wasmi v0.4.3 (/home/jlb6740/github_dev/wasmi) wasmi v0.4.3(/ home / jlb6740 / github_dev / wasmi)
    ├── byteorder v1.3.1 (/home/jlb6740/github_dev/byteorder) ├──字节顺序v1.3.1(/ home / jlb6740 / github_dev / byteorder)
    ├── hashbrown v0.1.8 (/home/jlb6740/github_dev/hashbrown) ├──puckbrownv0.1.8(/ home / jlb6740 / github_dev / hashbrown)
    │ ├── byteorder v1.3.1 (/home/jlb6740/github_dev/byteorder) ( ) │├──byalorderv1.3.1(/ home / jlb6740 / github_dev / byteorder)(
    │ └── scopeguard v0.3.3 (/home/jlb6740/github_dev/scopeguard) │└──scopeguard v0.3.3(/ home / jlb6740 / github_dev / scopeguard)
    ├── libm v0.1.2 ├──libmv0.1.2
    ├── memory_units v0.3.0 ├──memory_unitsv0.3.0
    └── parity-wasm v0.31.0 (/home/jlb6740/github_dev/parity-wasm) └──parent-wasm v0.31.0(/ home / jlb6740 / github_dev / parity-wasm)
    └── byteorder v1.3.1 (/home/jlb6740/github_dev/byteorder) ( ) └──byodeorderv1.3.1(/ home / jlb6740 / github_dev / byteorder)(

  2. I tried using cargo rustc --verbose … but at this time verbose does not indicate anything was using default features which may include using std 我尝试使用货物rustc --verbose ...但此时详细并未表明任何使用默认功能的内容可能包括使用std

  3. I tried using cargo metadata … this generated a long list of dependencies that was hard to parse, but I did see some instances where scopeguard and byteorder had default features requiring std support. 我尝试使用货物元数据...这产生了一长串难以解析的依赖关系,但我确实看到了一些范围,其中scopeguard和byteorder具有需要std支持的默认功能。 I downloaded all of these crates and just hardcoded attributes so that the crates would only build with no_std support. 我下载了所有这些板条箱和硬编码属性,这样箱子只能用no_std支持构建。

  4. I tried looking at the deps/ output and did an nm on all of the rlibs to see if any of the libraries used symbols found in std. 我试着查看deps / output并在所有rlib上做了一个nm来查看是否有任何库使用了std中的符号。 I could not find that that was the case. 我找不到那种情况。 I thought rlibs were like static libraries and that anything they used would be included in the rlib but apparently not. 我认为rlibs就像静态库,他们使用的任何东西都会被包含在rlib中,但显然不是。

  5. I looked at cargo rustc -- -C --print-link-args to check out linker flags but I could not find anything obvious telling me it was bringing in std lib. 我查看货物rustc - -C --print-link-args检查链接器标志,但我找不到任何明显的告诉我它引入了std lib。

None of these things helped me to pinpoint what was introducing std lib. 这些都没有帮助我确定引入std lib的内容。 Ultimately the suggestion at the rust forums was to use cargo check for a target that does not allow std lib at all. 最终,在Rust论坛上的建议是使用货物检查来完成一个不允许使用std lib的目标。 Those with a * listed here: enter link description here have only core support. 这里列出* :在这里输入链接描述只有核心支持。 I tried that, running with --target=thumbv7m-none-eabi and saw: 我试过,用--target=thumbv7m-none-eabi并看到:

error[E0463]: can't find crate for alloc 错误[E0463]:无法找到用于alloc的包
–> /home/jlb6740/github_dev/hashbrown/src/lib.rs:44:1 - > /home/jlb6740/github_dev/hashbrown/src/lib.rs:44:1
| |
44 | 44 | extern crate std as alloc; extern crate std as alloc;
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^ can't find crate ^^^^^^^^^^^^^^^^^^^^^^^^^^找不到包装箱

Turns out it was hashbrown which was a dependency of a dependency of my executable. 原来它是hashbrown,它是我的可执行文件的依赖项的依赖项。 It built no_std by default but had an extern std linked under a different name and which was guarded by a feature called “nightly”. 它默认构建了no_std,但是有一个extern std以不同的名字链接,并被一个名为“nightly”的功能保护。 The guard was disabled in my efforts to not build anything but no_std. 在我努力不建立任何东西而不是no_std时,警卫被禁用了。 Nothing I'd tried alerted me to the crate which was responsible until this. 没有什么我试过提醒我的箱子,直到这个负责。 Seems there should be a better way to get a more comprehensive list of crate dependencies than what cargo tree provided, but changing the wasmi cargo to make sure the nightly feature was set solved my issue. 似乎应该有一个更好的方法来获得比货物树提供的更全面的箱子依赖性列表,但改变wasmi货物以确保夜间特征设置解决了我的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM