Features Examples - The Cargo Book

# Features Examples

The following illustrates some real-world examples of features in action.

## Minimizing build times and file sizes

Some packages use features so that if the features are not enabled, it reduces the size of the crate and reduces compile time. Some examples are:

- `syn` is a popular crate for parsing Rust code. Since it is so popular, it is helpful to reduce compile times since it affects so many projects. It has a clearly documented list of features which can be used to minimize the amount of code it contains.
- `regex` has a several features that are well documented. Cutting out Unicode support can reduce the resulting file size as it can remove some large tables.
- `winapi` has a large number of features that limit which Windows API bindings it supports.
- `web-sys` is another example similar to `winapi` that provides a huge surface area of API bindings that are limited by using features.

## Extending behavior

The `serde_json` package has a `preserve_order` feature which changes the behavior of JSON maps to preserve the order that keys are inserted. Notice that it enables an optional dependency `indexmap` to implement the new behavior.

When changing behavior like this, be careful to make sure the changes are SemVer compatible. That is, enabling the feature should not break code that usually builds with the feature off.

## `no_std` support

Some packages want to support both `no_std` and `std` environments. This is useful for supporting embedded and resource-constrained platforms, but still allowing extended capabilities for platforms that support the full standard library.

The `wasm-bindgen` package defines a `std` feature that is enabled by default. At the top of the library, it unconditionally enables the `no_std` attribute. This ensures that `std` and the `std` prelude are not automatically in scope. Then, in various places in the code (example1, example2), it uses `#[cfg(feature = "std")]` attributes to conditionally enable extra functionality that requires `std`.

## Re-exporting dependency features

It can be convenient to re-export the features from a dependency. This allows the user depending on the crate to control those features without needing to specify those dependencies directly. For example, `regex` re-exports the features from the `regex_syntax` package. Users of `regex` don’t need to know about the `regex_syntax` package, but they can still access the features it contains.

## Vendoring of C libraries

Some packages provide bindings to common C libraries (sometimes referred to as “sys” crates). Sometimes these packages give you the choice to use the C library installed on the system, or to build it from source. For example, the `openssl` package has a `vendored` feature which enables the corresponding `vendored` feature of `openssl-sys`. The `openssl-sys` build script has some conditional logic which causes it to build from a local copy of the OpenSSL source code instead of using the version from the system.

The `curl-sys` package is another example where the `static-curl` feature causes it to build libcurl from source. Notice that it also has a `force-system-lib-on-osx` feature which forces it to use the system libcurl, overriding the static-curl setting.

## Feature precedence

Some packages may have mutually-exclusive features. One option to handle this is to prefer one feature over another. The `log` package is an example. It has several features for choosing the maximum logging level at compile-time described here. It uses `cfg-if` to choose a precedence. If multiple features are enabled, the higher “max” levels will be preferred over the lower levels.

## Proc-macro companion package

Some packages have a proc-macro that is intimately tied with it. However, not all users will need to use the proc-macro. By making the proc-macro an optional-dependency, this allows you to conveniently choose whether or not it is included. This is helpful, because sometimes the proc-macro version must stay in sync with the parent package, and you don’t want to force the users to have to specify both dependencies and keep them in sync.

An example is `serde` which has a `derive` feature which enables the `serde_derive` proc-macro. The `serde_derive` crate is very tightly tied to `serde`, so it uses an equals version requirement to ensure they stay in sync.

## Nightly-only features

Some packages want to experiment with APIs or language features that are only available on the Rust nightly channel. However, they may not want to require their users to also use the nightly channel. An example is `wasm-bindgen` which has a `nightly` feature which enables an extended API that uses the `Unsize` marker trait that is only available on the nightly channel at the time of this writing.

Note that at the root of the crate it uses `cfg_attr` to enable the nightly feature. Keep in mind that the `feature` attribute is unrelated to Cargo features, and is used to opt-in to experimental language features.

The `simd_support` feature of the `rand` package is another example, which relies on a dependency that only builds on the nightly channel.

## Experimental features

Some packages have new functionality that they may want to experiment with, without having to commit to the stability of those APIs. The features are usually documented that they are experimental, and thus may change or break in the future, even during a minor release. An example is the `async-std` package, which has an `unstable` feature, which gates new APIs that people can opt-in to using, but may not be completely ready to be relied upon.