[Solved] How to troubleshoot why (and prevent) cargo/rustc links in crate std when no_std is specified

#1

Hi,

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. New to Rust, I am simply piecing together instructions. As noted here stackoverflow, I have included I believe all the necessary attributes and defined my panic_impl function. This executable compiles until I try to actually call code from wasmi. In this case I get a message:

error[E0152]: duplicate lang item found: panic_impl.
–> src/main.rs:32:1
|
32 | / pub extern fn panic(info: &PanicInfo) -> ! {
33 | | // unsafe {
34 | | // printf(b"Panic\n" as *const u8);
35 | | //printf!(“Panic\n”);
36 | | // }
37 | | loop {}
38 | | }
| |
^
|
= note: first defined in crate std.

error: aborting due to previous error

For more information about this error, try rustc --explain E0152.
error: Could not compile driver.

even though I have built wasmi with no_std support as well. I’ve followed the leads of many similar issues posted … namely one here: https://github.com/rust-lang/cargo/issues/5730 but doing things such as downloading dependencies and making sure their cargo.toml do not support use_std does not help. I btw, used cargo metadata and cargo tree to help track dependencies. Specifically I am looking for help to troubleshoot this. This seems like it should be called a linking error, but cargo/rustc alerts me that it could not compile which makes me wonder when does the check take place for duplicate lang items? I thought the option for rustc to print-link-args would help but I do not see anything glaring flag “–linking-in-rust-std-lib”. I tried to look at nm of the deps used to build this driver that links in wasmi, and none of those files contain std lib code. Any pointers on how to troubleshoot this and ultimately correct this issue would be helpful. Also, new to this forum, I am not sure if this is the best place to post this or if this type of concern should be posted on github or where.

jlb6740

0 Likes

#2

You probably have dependencies that are not no_std.

1 Like

#3

Hi Jethrogb,

Thanks for the response. That is the question … how do I troubleshoot what that dependency is? As a user of some crate “foo” that claims to support no_std I’d expect all the dependencies it pulls in for the no_std build to work, would also compile with no_std support, else I don’t see how crate “foo” can make claims about not using std lib. Despite having this initial assumption (which I guess is wrong) I have seen bugs as I’ve pointed to that show that at the very least you can inadvertently (or maybe due to a cargo poor design) build the no_std version of crates or dependencies of crates due to support for test builds and build and dev dependencies. After reading bugs filed concerning these issues it is a guess (and only a guess) that this is my case not something else, but at this point I am looking for a systematic approach to identifying that crate/dependency. I’ve tried these things:

  1. using cargo tree to list dependencies to list all the crate dependencies:
    wasmi v0.4.3 (/home/jlb6740/github_dev/wasmi)
    ├── byteorder v1.3.1 (/home/jlb6740/github_dev/byteorder)
    ├── hashbrown v0.1.8 (/home/jlb6740/github_dev/hashbrown)
    │ ├── byteorder v1.3.1 (/home/jlb6740/github_dev/byteorder) ()
    │ └── scopeguard v0.3.3 (/home/jlb6740/github_dev/scopeguard)
    ├── libm v0.1.2
    ├── memory_units v0.3.0
    └── parity-wasm v0.31.0 (/home/jlb6740/github_dev/parity-wasm)
    └── byteorder v1.3.1 (/home/jlb6740/github_dev/byteorder) (
    )

Nothing here says: “I am bringing in crate std”.

  1. I tried using cargo rustc --verbose … but at this time verbose does not indicate anything was using default features which may include using std

  2. 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. I downloaded all of these crates and just hardcoded attributes so that the crates would only build with no_std support.

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

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

Do you have any suggestions on how to identify the dependency?

0 Likes

#4

I would try cargo check for a target that doesn’t have std at all, and see what fails. Those with a * in the std column of this table have only core support:
https://forge.rust-lang.org/platform-support.html#tier-3

3 Likes

#5

Hi Cuviper,

Thanks a lot! That did the trick and helped me pinpoint the troubled crate. I downloaded a new target using rustup and set that to the target --target=thumbv7m-none-eabi

error[E0463]: can’t find crate for alloc
–> /home/jlb6740/github_dev/hashbrown/src/lib.rs:44:1
|
44 | extern crate std as alloc;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ can’t find crate

Turns out it was hashbrown which was a dependency of a dependency. 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”. The guard was disabled in my efforts to not build anything but no_std. Nothing I’d tried alerted me to the crate which was responsible but your trick did the trick. Seems there should be a better way to get a more comprehensive list of crate dependencies than what cargo tree provided, but for the std crate at least this worked … Thanks.

0 Likes