Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Features required for dependencies influenced by build-dependencies. #107845

Closed
WorksButNotTested opened this issue Feb 9, 2023 · 8 comments
Closed
Labels
A-linkage Area: linking into static, shared libraries and binaries C-discussion Category: Discussion or questions that doesn't represent real issues. T-cargo Relevant to the cargo team, which will review and decide on the PR/issue.

Comments

@WorksButNotTested
Copy link

I am trying to build a #![no_std] crate, but encountering the following error from the linker...

error: the `#[alloc_error_handler]` in this crate conflicts with allocation error handler in: std

error[E0152]: found duplicate lang item `panic_impl`
  --> test/src/lib.rs:23:1
   |
23 | fn panic(info: &PanicInfo) -> ! {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: the lang item is first defined in crate `std` (which `memchr` depends on)
   = note: first definition in `std` loaded from /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libstd-bca906efb5fb081f.so, /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libstd-bca906efb5fb081f.rlib
   = note: second definition in the local crate (`test2`)

error[E0152]: found duplicate lang item `eh_personality`
  --> test/src/lib.rs:30:1
   |
30 | extern "C" fn rust_eh_personality() {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: the lang item is first defined in crate `std` (which `memchr` depends on)
   = note: first definition in `std` loaded from /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libstd-bca906efb5fb081f.so, /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libstd-bca906efb5fb081f.rlib
   = note: second definition in the local crate (`test2`)

For more information about this error, try `rustc --explain E0152`.
error: could not compile `test2` due to 3 previous errors
[cargo-make] ERROR - Error while executing command, exit code: 101
[cargo-make] WARN - Build Failed.

Even though my crate is no_std, the linker is seemingly trying to link std nonetheless (indeed if I comment out my implementations of the above functions in my crate, it links sucessfully). However, if a crate is marked no_std, you wouldn't expect the std crate to be linked in no matter what, so this seems pretty odd?

Anyway, I then investigate the dependencies for my crate to see where memchr is being included as a dependency. So as expected, it is included by cstr_core from my Cargo.toml. But also as a build dependency from bindgen.

cstr_core = {version = "0.2.6", features = ["alloc"], default-features = false }
cargo tree --no-dedupe -p test2 -i memchr --target armv7-unknown-linux-gnueabihf -f "{p} # {f}"

memchr v2.5.0 # std
└── nom v7.1.3 # alloc,std
   └── cexpr v0.6.0 # 
      └── bindgen v0.63.0 # default,log,logging,runtime,which,which-rustfmt
            [build-dependencies]            
            └── test2 v0.1.0 (/home/share/git/test2/test2)

memchr v2.5.0 # std
└── cstr_core v0.2.6 # alloc
   └── test2 v0.1.0 (/home/share/git/test2/test2) 

However, cstr_core should not include the std feature of memchr (e.g. the std feature should be required only at build time and not needed to be linked into the resulting binary). A similar project also linked against cstr_core, but without using bindgen shows no such depdendency?

cargo tree --no-dedupe -p test -i memchr --target armv7-unknown-linux-gnueabihf -f "{p} # {f}"

memchr v2.5.0 # 
└── cstr_core v0.2.6 # alloc
    └── test1 v0.1.0 (/home/share/git/test/test)

Have I mis-understood something?

$ rustc --version
rustc 1.68.0-nightly (c7572670a 2023-01-03)
$ cargo --version
cargo 1.68.0-nightly (2381cbdb4 2022-12-23)
@Xaeroxe
Copy link
Contributor

Xaeroxe commented Feb 9, 2023

If you're building in a virtual workspace then it's very likely you need to opt in to resolver version 2. Read this for more information https://doc.rust-lang.org/cargo/reference/resolver.html#feature-resolver-version-2

@Xaeroxe
Copy link
Contributor

Xaeroxe commented Feb 9, 2023

You might have already noticed this, but you should read this too

https://doc.rust-lang.org/cargo/reference/resolver.html#resolver-versions

@WorksButNotTested
Copy link
Author

WorksButNotTested commented Feb 10, 2023

@Xaeroxe awesome. Thanks so much for pointing me at this, you've saved me so much time! I'd have struggled to find this by myself!

@WorksButNotTested
Copy link
Author

So it seems my issue is two-fold:

  1. When a crate is marked #![no_std] cargo may still link std into it if one of its dependencies (or perhaps build-dependencies) requires it.
    • This does not result in an error, or a warning. Should this be reconsidered?
  2. The issue of feature unification is remedied by version 2 of the resolver, but this is not readily apparent to the user. The resolver version is pretty arcane and so the UX could be improved in this regard to help the user to at least learn of its existence.
    • When std is linked into a #![no_std] crate, the user is not pointed to use cargo tree to investigate the issues.
    • When using cargo tree it doesn't highlight any features which may have been included in the target as a result of feature re-unification.
    • When using cargo tree it does not warn that resolver v1 is being used, nor point the user at the documentation for the resolver versions when feature unification differences may affect their build.
    • Resolver defaults to v1 even if all of the crates within the workspace are marked with edition = "2021" without any warning about a potential inconsistency.

@jyn514
Copy link
Member

jyn514 commented Apr 26, 2023

When a crate is marked #![no_std] cargo may still link std into it if one of its dependencies (or perhaps build-dependencies) requires it.

I don't think this should error, no, it's reasonable for a library to be unconditionally no_std but be used by a binary that links std.

The issue of feature unification is remedied by version 2 of the resolver, but this is not readily apparent to the user.

You should report this in rust-lang/cargo; I don't think rustc has enough information to give a useful error.

@jyn514 jyn514 added A-linkage Area: linking into static, shared libraries and binaries T-cargo Relevant to the cargo team, which will review and decide on the PR/issue. C-discussion Category: Discussion or questions that doesn't represent real issues. labels Apr 26, 2023
@weihanglo
Copy link
Member

When a crate is marked #![no_std] cargo may still link std into it if one of its dependencies (or perhaps build-dependencies) requires it.

The issue of feature unification is remedied by version 2 of the resolver, but this is not readily apparent to the user.

A couple of (stale) open pull requests addressing this. Feel free to jump in and move them forward.

@jyn514
Copy link
Member

jyn514 commented Apr 26, 2023

@weihanglo could you move this to the cargo issue tracker please?

@weihanglo
Copy link
Member

Given we have other issues covering this, I propose to close it as duplicate.

@jyn514 jyn514 closed this as not planned Won't fix, can't repro, duplicate, stale Apr 26, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-linkage Area: linking into static, shared libraries and binaries C-discussion Category: Discussion or questions that doesn't represent real issues. T-cargo Relevant to the cargo team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

4 participants