Cargo features and optional dependencies

I'd like to know more about disabling compilation of parts of your crate using features.

I know there is:

#[cfg(feature = "foo")]
pub fn foo() { ... }

which would presumably cause rustc to ignore this function when compiling unless that feature is enabled in Cargo,toml

[dependencies]
my-crate = { version = "0.1.0", features = ["foo"] }

But I don't know if I can specify to not compile a used feature that my-crate depends on:

use external::CanIPleaseNotCompileThis

#[cfg(feature = "bar")]
fn bar() -> impl CanIPleaseNotCompileThis

Sorry for the contrived example!

I think this might be what optional dependencies are for having skimmed this page of the cargo book Specifying Dependencies - The Cargo Book

What I'm really doing, (to avoid the X-Y problem), is have a shared crate that both a client and server (webapp) depend on to share types that can be sent back and forth (i.e. some structs that model the API requests and responses).
I'd like to implement rocket's FromForm for the responses so the server can use it when handling routes

but... rocket won't compile for the wasm32-unknown-unknown target used by my client crate, so if I add rocket as a dependency to the shared crate then I can't build the client at all*

Unless I can "hide it behind a feature". Though apparently "mutually exclusive" use of features is a bad idea

*I get ring build script errors, I did have a quick google and it seems to be a fairly gnarly problem I'd like to avoid

I think I've just realised that even if I could hide rocket compilation behind a feature I'd still end up stuck with having a different struct for the client and server which sort of defeats the purpose of having a shared crate :confused:

I did wonder whether the new relaxed orphan rule would be of any help here, but I suspect not since it's an external type and and external trait and no local type parameter. Maybe there's a pattern where I could introduce some local type parameters...

had a (very small) brainwave - serde must do this, they have derive behind a feature!

and sure enough:
https://stackoverflow.com/questions/42046327/conditionally-derive-based-on-feature-flag

I'm going to try this now :slight_smile:

shepmaster strikes again :smiley:

It works :slight_smile: that was surprisingly easy! :slight_smile: cargo is great isn't it?

For the record, what I ended up doing if you're curious is here
It's basically as simple as:

shared/Cargo.toml

[dependencies]
rocket = { version = "0.4.2", optional = true }

server/Cargo.toml

[dependencies]
shared = { path = "../shared", features = ["rocket"] }

shared/src/lib.rs

#[cfg(feature = "rocket")]
use rocket::request::FromForm;

#[cfg_attr(feature = "rocket", derive(FromForm))]
struct Foo {
    ...
}
1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.