When compiling a Rust workspace composed of multiple packages, is there a way to make cargo
error when the succesfull compilation of a package foo
depends on features that are not enabled by foo
nor its dependencies?
Let me give a concrete example. With the workspace described below cargo build
succeeds, but cargo build -p foo
gives a compilation error because a tokio
feature is missing in foo/Cargo.toml
:
error[E0432]: unresolved import `tokio::io::AsyncWriteExt`
--> foo/src/lib.rs:1:5
|
1 | use tokio::io::AsyncWriteExt;
| ^^^^^^^^^^^-------------
| | |
| | help: a similar name exists in the module: `AsyncWrite`
| no `AsyncWriteExt` in `io`
For more information about this error, try `rustc --explain E0432`.
error: could not compile `foo` due to previous error
This is bad! cargo build
happily accepts usages of indirect dependencies. That is, changing code that is not in foo
nor in its dependencies (i.e. removing the io-util
feature from bar/Cargo.toml
) can introduce compilation errors in foo
. I would like to detect and prevent this without having to try each time to compile each single package individually.
Structure of the workspace:
.
├── foo
│ ├── src
│ │ └── lib.rs
│ └── Cargo.toml
├── bar
│ ├── src
│ │ └── main.rs
│ └── Cargo.toml
└── Cargo.toml
./foo/src/lib.rs
:
use tokio::io::AsyncWriteExt;
pub fn dummy(_: impl AsyncWriteExt) {
unimplemented!()
}
./foo/Cargo.toml
:
[package]
name = "foo"
version = "0.1.0"
edition = "2021"
[dependencies]
"tokio" = "1.21.2"
./bar/src/main.rs
:
fn main() {
println!("Hello, world!");
}
./bar/Cargo.toml
:
[package]
name = "bar"
version = "0.1.0"
edition = "2021"
[dependencies]
"tokio" = { version = "1.21.2", features = ["io-util"] }
"foo" = { path = "../foo" }
./Cargo.toml
:
[workspace]
members = [
"foo",
"bar",
]