Awesome article, I think the ecosystem really needed one like this one! ![]()
Trick: you can dodge it by emiting a "raw --cfg" rather than a cargo feature:
-
Add this to the
Cargo.tomlto make it work on docs.rs[package.metadata.docs.rs] all-features = true rustdocflags = ["--cfg", "docs"] -
Add this to the
.cargo/configfile (create it if it doesn't exist) to make it work locally:[build] rustdocflags = ["--cfg", "docs"] -
And then the
src/lib.rsas you suggested; I personally do something like:#![cfg_attr(docs, feature(doc_cfg, external_doc), doc(include = "../README.md"), )] #![doc = ""] // empty doc line to handle missing doc warning when the feature is missing. -
Annotating the
cfg-gated items with:#[cfg(feature = "example")] #[cfg_attr(docs, doc(cfg(feature = "example")))]But this is repetitive, (plus it requires
cargo doc --all-featureslocally), so a macro can come in handy:macro_rules! doc_cfg {( #[doc_cfg( $($cfg:tt)* )] $item:item ) => ( #[cfg_attr(docs, doc(cfg( $($cfg)* )))] #[cfg(any(docs, $($cfg)*))] // also include the item for documentation $item )}to be used as:
doc_cfg! { #[doc_cfg(feature = "example")] pub struct Foo; // etc. }or, if using
#[macro_rules_attribute], this can be made smoother by doing:/// At the top level: `src/lib.rs` #[macro_use] extern crate macro_rules_attribute;#[macro_rules_attribute(doc_cfg!)] #[doc_cfg(feature = "example")] pub struct Foo; // etc.This, of course, is to have a general tool for any feature / combination of
cfgs.
But usually a crate has one or two recurring cfgs, such as#[cfg(feature = "std")], for which a more specialized macro is simpler and can handle multiple items at once:macro_rules! cfg_std {( $( $item:item )* ) => ( $( #[cfg(any(docs, feature = "std"))] #[cfg_attr(docs, doc(cfg(feature = "std")))] $item )* )} cfg_std! { pub struct Foo { ... } impl Foo { ... } }