Features Examples - The Cargo Book (original) (raw)

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:

Extending behavior

The serde_json package has a preserve_order featurewhich changes the behavior of JSON maps to preserve the order that keys are inserted. Notice that it enables an optional dependencyindexmap to implement the new behavior.

When changing behavior like this, be careful to make sure the changes areSemVer 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, itunconditionally 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_syntaxpackage. 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. Theopenssl-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-curlfeature 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-bindgenwhich has a nightly feature which enables anextended 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 attributeis 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-stdpackage, 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.