Blog post: Crate publishing tips and guidelines

Awesome article, I think the ecosystem really needed one like this one! :clap:

Trick: you can dodge it by emiting a "raw --cfg" rather than a cargo feature:

  • Add this to the Cargo.toml to make it work on docs.rs

    [package.metadata.docs.rs]
    all-features = true
    rustdocflags = ["--cfg", "docs"]
    
  • Add this to the .cargo/config file (create it if it doesn't exist) to make it work locally:

    [build]
    rustdocflags = ["--cfg", "docs"]
    
  • And then the src/lib.rs as 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-features locally), 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 { ... }
    }
    
3 Likes