Features - The Cargo Book

## Features

Cargo supports features to allow expression of:

- conditional compilation options (usable through `cfg` attributes);
- optional dependencies, which enhance a package, but are not required; and
- clusters of optional dependencies, such as `postgres-all`, that would include the `postgres` package, the `postgres-macros` package, and possibly other packages (such as development-time mocking libraries, debugging tools, etc.).

A feature of a package is either an optional dependency, or a set of other features.

### The `[features]` section

Features are defined in the `[features]` table of `Cargo.toml`. The format for specifying features is:

    [package]
    name = "awesome"

    [features]
    # The default set of optional packages. Most people will want to use these
    # packages, but they are strictly optional. Note that `session` is not a package
    # but rather another feature listed in this manifest.
    default = ["jquery", "uglifier", "session"]

    # A feature with no dependencies is used mainly for conditional compilation,
    # like `#[cfg(feature = "go-faster")]`.
    go-faster = []

    # The `secure-password` feature depends on the bcrypt package. This aliasing
    # will allow people to talk about the feature in a higher-level way and allow
    # this package to add more requirements to the feature in the future.
    secure-password = ["bcrypt"]

    # Features can be used to reexport features of other packages. The `session`
    # feature of package `awesome` will ensure that the `session` feature of the
    # package `cookie` is also enabled.
    session = ["cookie/session"]

    [dependencies]
    # These packages are mandatory and form the core of this package’s distribution.
    cookie = "1.2.0"
    oauth = "1.1.0"
    route-recognizer = "=2.1.0"

    # A list of all of the optional dependencies, some of which are included in the
    # above `features`. They can be opted into by apps.
    jquery = { version = "1.0.2", optional = true }
    uglifier = { version = "1.5.3", optional = true }
    bcrypt = { version = "*", optional = true }
    civet = { version = "*", optional = true }

To use the package `awesome`:

    [dependencies.awesome]
    version = "1.3.5"
    default-features = false # do not include the default features, and optionally
                             # cherry-pick individual features
    features = ["secure-password", "civet"]

### Rules

The usage of features is subject to a few rules:

- Feature names must not conflict with other package names in the manifest. This is because they are opted into via `features = [...]`, which only has a single namespace.
- With the exception of the `default` feature, all features are opt-in. To opt out of the default feature, use `default-features = false` and cherry-pick individual features.
- Feature groups are not allowed to cyclically depend on one another.
- Dev-dependencies cannot be optional.
- Features groups can only reference optional dependencies.
- When a feature is selected, Cargo will call `rustc` with `--cfg feature="${feature_name}"`. If a feature group is included, it and all of its individual features will be included. This can be tested in code via `#[cfg(feature = "foo")]`.

Note that it is explicitly allowed for features to not actually activate any optional dependencies. This allows packages to internally enable/disable features without requiring a new dependency.

> Note: crates.io requires feature names to only contain ASCII letters, digits, `_`, or `-`.

### Usage in end products

One major use-case for this feature is specifying optional features in end-products. For example, the Servo package may want to include optional features that people can enable or disable when they build it.

In that case, Servo will describe features in its `Cargo.toml` and they can be enabled using command-line flags:

    $ cargo build --release --features "shumway pdf"

Default features could be excluded using `--no-default-features`.

### Usage in packages

In most cases, the concept of optional dependency in a library is best expressed as a separate package that the top-level application depends on.

However, high-level packages, like Iron or Piston, may want the ability to curate a number of packages for easy installation. The current Cargo system allows them to curate a number of mandatory dependencies into a single package for easy installation.

In some cases, packages may want to provide additional curation for optional dependencies:

- grouping a number of low-level optional dependencies together into a single high-level feature;
- specifying packages that are recommended (or suggested) to be included by users of the package; and
- including a feature (like `secure-password` in the motivating example) that will only work if an optional dependency is available, and would be difficult to implement as a separate package (for example, it may be overly difficult to design an IO package to be completely decoupled from OpenSSL, with opt-in via the inclusion of a separate package).

In almost all cases, it is an antipattern to use these features outside of high-level packages that are designed for curation. If a feature is optional, it can almost certainly be expressed as a separate package.