Guidance on optional functionality: crates vs features

When designing a library, there is often functionality that you want to make entirely optional. Often times this can be accomplished in two ways: splitting the library into multiple crates, or keeping it in one but gating some parts with features. (And of course, both methods can be used.)

I'm wondering if there are any blog posts or other references that provide a nice rundown of the tradeoffs involved, when it is preferred to use one over the other, conventions in the ecosystem, etc.

A personal observation based on dealing with crate authors who see things differently: features are additive. Enabling a feature adds something. It does not enable something. If the thing is something that is enabled / disabled then it's a flag in the API followed by some if-statements in the code.

In shorter broader terms, please trust the optimizer. I've seen features used to essentially eliminate dead code in the belief that that is some sort of optimization. Please don't do that. The optimizer will happily do that for us.

Another personal observation...

...seems to lead to better design and structure. You've posed the question as either-or. Based on that I'd appreciate you leaning towards multiple crates when possible.

For what it's worth, where I work we've stopped using features with our code. It's not something being dictated. It's just natural selection.

One of the big problems right now with features is that their discoverability and self-documenting abilities are really really poor. Features are not structured and hierarchical like crates and modules.

They do not allow doc comments or toml description fields to be attached to them, and even though they are listed by rustdoc, I doubt many have even noticed the link to the features page. In any case, there is nothing on the page except the names and dependencies of the features, because, again, there simply is no way to attach any metadata to features. Documenting features requires discipline from a crate author.

IDE support for features is also poor. At least in IDEA there is no way to quickly toggle features on and off and have it reflected in completion and type checking. (They are alien to the Java build model, which I’m sure causes some impedance mismatch in the IDEA plugin…)

There is also no standard way for a crate author to tell Cargo to build and test all the n up to 2^n feature combinations to confirm they all work as expected given the additivity assumption. I’m not sure if there exists a third-party addon to do that.

2 Likes

This is possible on CLion though.

EDIT/PRECISATION:
It is possible to toggle the features of your crate (the one being developed), not dependency ones. For them I usually just enables the features in Cargo.toml and see them enabled in my code.

1 Like