问题
So we are currently trying to compile some Rust code that we can then link to some C code. To do this we are using Bindgen to generate an FFI, and then we will use it to call some C functions from Rust.
However, we must first have the crate "libc" as a dependency in the Cargo.toml file of the project. The project we are currently working on demands that we use the crate wide !#[no_std] attribute, as we don't want the entire stdlib of Rust. We only need the core. The libc crate says we can "request" it not be linked to the standard library by putting some options in the Cargo.toml file, namely:
[dependencies]
libc = { version = "0.2", default-features = false }
This is all fine and dandy, but when we try to compile we get the following error message.
Ubuntu:~/nautilus/src/rust/example# cargo build
Compiling example v0.0.0 (/home/me/nautilus/src/rust/example)
error[E0152]: duplicate lang item found: `panic_impl`.
--> src/lib.rs:33:1
|
33 | / pub fn nk_rust_panic(_info: &PanicInfo) -> !
34 | | {
35 | | // should call nk_panic here...
36 | | loop { }
37 | | }
| |_^
|
= 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 `example`.
To learn more, run the command again with --verbose.
E0152 is the following
A lang item was redefined.
Erroneous code example:
```
#![feature(lang_items)]
#[lang = "arc"]
struct Foo; // error: duplicate lang item found: `arc`
```
Lang items are already implemented in the standard library. Unless you are
writing a free-standing application (e.g. a kernel), you do not need to provide
them yourself.
You can build a free-standing crate by adding `#![no_std]` to the crate
attributes:
```
#![no_std]
```
Our lib.rs file has #![no_std] already in it, but it appears that since libc would normally link against stdlib, that maybe Rust thinks that we cannot have a custom panic handler if we are using libc.
The problem relieves itself when we remove libc from the Cargo.toml file, and remove the extern crate lib
from lib.rs.
lib.rs
// no stdlib
#![no_std]
// Give us this feature to override?
#![feature(start)]
#![feature(lang_items)]
// avoid buildins - we want it to use our library
#![no_builtins]
// The following cruft is here to handle Rust->OS dependencies
// currently only one: Rust needs to know how to panic
use core::panic::PanicInfo;
extern crate libc;
#[panic_handler]
#[no_mangle]
pub fn nk_rust_panic(_info: &PanicInfo) -> !
{
// should call nk_panic here... (panic handler of OS)
loop { }
}
Cargo.toml
[package]
name = "example" # this is for core-kernel
version = "0.0.0"
[lib]
crate-type = ["staticlib"]
[dependencies]
libc = { version = "0.2", default-features = false }
[build-dependencies]
bindgen = "0.42.2"
[profile.dev]
panic = "abort" # no stack unwind on rust panic
[profile.release]
panic = "abort" # no stuck unwind on rust panic
So, in sum, does using libc as a dependency make us unable to use our own custom panic handler? Are there any wonky compiler flags we can pass directly to rustc to eliminate this problem?
Compiler is 1.32.0-nightly Libc version is libc v0.2.44
回答1:
You are running into a bug in Cargo.
Features are a bit subtle. They can be enabled by any transitive dependency, which is expected behaviour. However, they can even be enabled by transitive build dependencies, which is a bug.
来源:https://stackoverflow.com/questions/53545506/does-rust-libc-crate-inhibit-the-compilation-of-custom-panic-handler