Move features to a separate chapter.

This commit is contained in:
Eric Huss 2019-12-20 20:43:37 -08:00
parent f453bed7f5
commit dc81356ef1
8 changed files with 148 additions and 136 deletions

View file

@ -23,6 +23,7 @@
* [The Manifest Format](reference/manifest.md)
* [Cargo Targets](reference/cargo-targets.md)
* [Workspaces](reference/workspaces.md)
* [Features](reference/features.md)
* [Profiles](reference/profiles.md)
* [Configuration](reference/config.md)
* [Environment Variables](reference/environment-variables.md)

View file

@ -182,7 +182,7 @@ manifest is located.
[edition guide]: ../../edition-guide/index.html
[edition-field]: ../reference/manifest.md#the-edition-field
[environment variable]: ../reference/environment-variables.md
[feature]: ../reference/manifest.md#the-features-section
[feature]: ../reference/features.md
[git dependency]: ../reference/specifying-dependencies.md#specifying-dependencies-from-git-repositories
[git source]: ../reference/source-replacement.md
[integration-tests]: ../reference/cargo-targets.md#integration-tests

View file

@ -176,7 +176,7 @@ of `feature=`). Or an arbitrary key/value pair may be used with an `=` symbol
like `cargo:rustc-cfg=my_component="foo"`. The key should be a Rust
identifier, the value should be a string.
[cargo features]: manifest.md#the-features-section
[cargo features]: features.md
[conditional compilation]: ../../reference/conditional-compilation.md
[option-cfg]: ../../rustc/command-line-arguments.md#option-cfg

View file

@ -359,7 +359,7 @@ autobins = false
[dependencies]: specifying-dependencies.md
[dev-dependencies]: specifying-dependencies.md#development-dependencies
[documentation examples]: ../../rustdoc/documentation-tests.html
[features]: manifest.md#the-features-section
[features]: features.md
[nightly channel]: ../../book/appendix-07-nightly-rust.html
[package layout]: ../guide/project-layout.md
[package-edition]: manifest.md#the-edition-field

View file

@ -0,0 +1,134 @@
## 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:
```toml
[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 packages 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`:
```toml
[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:
```console
$ 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.
[crates.io]: https://crates.io/

View file

@ -6,6 +6,7 @@ The reference covers the details of various areas of Cargo.
* [The Manifest Format](manifest.md)
* [Cargo Targets](cargo-targets.md)
* [Workspaces](workspaces.md)
* [Features](features.md)
* [Profiles](profiles.md)
* [Configuration](config.md)
* [Environment Variables](environment-variables.md)

View file

@ -472,134 +472,6 @@ The `[profile]` tables provide a way to customize compiler settings such as
optimizations and debug settings. See [the Profiles chapter](profiles.md) for
more detail.
### The `[features]` section
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 format for specifying features is:
```toml
[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 packages 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`:
```toml
[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:
```console
$ 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.
### The `[patch]` Section
This section of Cargo.toml can be used to [override dependencies][replace] with
@ -717,7 +589,11 @@ dependencies][replace] section of the documentation.
"#building-dynamic-or-static-libraries": "cargo-targets.html#the-crate-type-field",
"#the-workspace-section": "workspaces.html#the-workspace-section",
"#virtual-manifest": "workspaces.html",
"#package-selection": "workspaces.html#package-selection"
"#package-selection": "workspaces.html#package-selection",
"#the-features-section": "features.html#the-features-section",
"#rules": "features.html#rules",
"#usage-in-end-products": "features.html#usage-in-end-products",
"#usage-in-packages": "features.html#usage-in-packages",
};
var target = fragments[window.location.hash];
if (target) {

View file

@ -510,8 +510,8 @@ run `rustc --print=cfg --target=x86_64-pc-windows-msvc`.
Unlike in your Rust source code, you cannot use
`[target.'cfg(feature = "fancy-feature")'.dependencies]` to add dependencies
based on optional features. Use [the `[features]`
section](manifest.md#the-features-section) instead:
based on optional features. Use [the `[features]` section](features.md)
instead:
```toml
[dependencies]
@ -618,8 +618,8 @@ default-features = false # do not include the default features, and optionally
features = ["secure-password", "civet"]
```
More information about features can be found in the
[manifest documentation](manifest.md#the-features-section).
More information about features can be found in the [features
chapter](features.md).
### Renaming dependencies in `Cargo.toml`