liveBook · Manning

Cargo feature

As explained in Write Powerful Rust Macros

A Cargo feature is a named compile-time configuration option that conditionally enables additive crate functionality or dependencies.

A Cargo feature is a named option for making crate functionality optional. Enable it when a consumer needs that capability; otherwise the associated code can stay out of the project. This is useful when one library exposes several macros but users need only some of them. section 10.3 section 10.9

Declare feature names in Cargo.toml, then guard imports, modules, and public macro entry points with #[cfg(feature = "...")]. Keeping feature-specific generation in its own module lets one conditional module import hide the supporting implementation as well as the macro. section 10.3

Listing 10.12 lib.rs featuring a feature
// other imports, mod input, mod output
#[cfg(feature = "struct")]              #1
use syn::DeriveInput;
#[cfg(feature = "struct")]     
mod struct_output;

// find_yaml_values
// function-like macro

#[cfg(feature = "struct")]               #2
#[proc_macro_attribute]
pub fn config_struct(attr: TokenStream, item: TokenStream)
    -> TokenStream {
    let input: ConfigInput = parse_macro_input!(attr);
    let ast: DeriveInput = parse_macro_input!(item);

    match find_yaml_values(&input) {
        Ok(values) => struct_output::generate_annotation_struct( #3
                ast, values, &input.exclude_from
            ).into(),                        
        Err(e) => e.into_compile_error().into()
    }
}

This listing gates the DeriveInput import, struct_output module, and config_struct attribute macro behind the same struct feature. section 10.3

A practical feature workflow is:

  • Add a feature entry such as struct = [] in Cargo.toml. section 10.3
  • Apply the same cfg condition to every import, module, and exported item required only by that feature. section 10.3
  • Test without the feature: using its macro should fail as unknown while unaffected macros continue working. section 10.3
  • Enable it at the dependency site with features = ["struct"] and verify the optional macro works again. section 10.3
  • Consider a default feature when an otherwise empty public macro surface would be awkward; consumers can disable defaults when needed. section 10.3

Optional attribute macro

A config-macro crate can expose a function-like macro normally while placing config_struct behind struct. A consumer that writes use config_macro::config_struct; must request config-macro = { path = "../config-macro", features = ["struct"] }; otherwise config_struct is unavailable. section 10.3 section 10.3

Features also commonly activate optional dependencies and reexports. For example, a derive feature can activate a derive-macro dependency, while a macros feature can activate a separate procedural-macro crate. Feature flags can therefore control both visible APIs and the code required to implement them. section 10.6 section 10.6

How Write Powerful Rust Macros covers it

How deep it goes
Demonstrates Cargo.toml declaration, cfg-gated imports and modules, consumer activation, failure testing, and default-feature trade-offs.
Examples
Uses an optional config_struct attribute macro, Serde derive macros, and Tokio’s macros feature and tokio-macros dependency.
What it assumes
Assumes familiarity with Cargo dependencies and procedural macros while briefly defining features as optional code.
What you can do after
Operate/configure optional macro APIs by declaring features, guarding code with cfg, and enabling requested features in dependencies.
How it connects
Connects feature flags with conditional compilation, optional dependencies, procedural macros, custom attributes, and default features.

Also explained in

Compare how 2 books explain cargo feature →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Write Powerful Rust Macros. The section links point to the parts of the book it draws on.