Explain Cargo features and how to define and enable them
This tests conditional compilation and optional dependency design in Rust. A strong answer outlines the [features] table, cfg attribute gating, and consumer enablement via --features or default features.
WHAT THIS TESTS: Your grasp of Cargo's conditional compilation model and how to design crates that stay lightweight. The interviewer wants to see that you understand features are compile-time switches, not runtime toggles, and that you know how to expose optional functionality without forcing dependencies on every consumer.
A GOOD ANSWER COVERS: First, state that features are defined in the [features] table of Cargo.toml, where each feature maps to an array of other features or optional dependencies. Second, explain that code is gated with #[cfg(feature = "name")] or the cfg macro so the compiler only includes it when the feature is enabled. Third, describe how consumers enable features on the command line with --features or through a dependency declaration using features = ["name"], and note that default features can be disabled with --no-default-features or default-features = false. Fourth, mention that optional dependencies implicitly create a feature of the same name, but this can be overridden with the dep: prefix if you want to hide the dependency name behind a nicer feature name or group multiple dependencies together.
COMMON WRONG ANSWERS: Treating features as runtime configuration flags is the biggest mistake; they are resolved entirely at compile time via rustc --cfg. Another red flag is forgetting that default features are automatically enabled for dependencies unless explicitly disabled, which can bloat downstream builds. Some candidates also miss that crates.io now limits new crates to a maximum of 300 features, or they fail to explain how optional dependencies tie into the feature system.
LIKELY FOLLOW-UPS: How do you handle feature unification when the same crate appears multiple times in the dependency graph with different feature sets? What is the SemVer implication of adding or removing a feature from the default set? When would you use weak dependencies or namespaced features with dep:? How do you avoid mutually exclusive features in a crate?
ONE CONCRETE EXAMPLE: Imagine a 2D image processing library. In Cargo.toml you write [features] webp = [] and [dependencies] libwebp-sys = { version = "0.9", optional = true }, then in your lib.rs you write #[cfg(feature = "webp")] pub mod webp;. A consumer adds your crate with image-lib = { version = "1.0", features = ["webp"] } to pull in the optional dependency, or uses --features webp when building directly.
Read the original → doc.rust-lang.org
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.