77 KiB
obj | repo | rev |
---|---|---|
application | https://github.com/rust-lang/cargo | 2024-08-30 |
cargo
Cargo is the official package manager for the Rust programming language. It serves as a build system, package manager, and dependency manager for Rust projects. Cargo makes it easy to manage, build, and distribute Rust projects, handling tasks such as compiling code, managing dependencies, and running tests.
cargo add
Add dependencies to a Cargo.toml
manifest file
Options
Option | Description |
---|---|
--no-default-features |
Disable the default features |
--default-features |
Re-enable the default features |
-F, --features <FEATURES> |
Space or comma separated list of features to activate |
--optional |
Mark the dependency as optional. The package name will be exposed as feature of your crate. |
--no-optional |
Mark the dependency as required. The package will be removed from your features. |
--rename <NAME> |
Rename the dependency |
--dry-run |
Don't actually write the manifest |
-q, --quiet |
Do not print cargo log messages |
-v, --verbose... |
Use verbose output (-vv very verbose/build.rs output) |
--manifest-path <PATH> |
Path to Cargo.toml |
--path <PATH> |
Filesystem path to local crate to add |
--git <URI> |
Git repository location |
--branch <BRANCH> |
Git branch to download the crate from |
--tag <TAG> |
Git tag to download the crate from |
--rev <REV> |
Git reference to download the crate from |
--registry <NAME> |
Package registry for this dependency |
--dev |
Add as development dependency. Dev-dependencies are not used when compiling a package for building, but are used for compiling tests, examples, and benchmarks. These dependencies are not propagated to other packages which depend on this package. |
--build |
Add as build dependency. Build-dependencies are the only dependencies available for use by build scripts (build.rs files). |
--target <TARGET> |
Add as dependency to the given target platform |
cargo build
Compile a local package and all of its dependencies
Options
Option | Description |
---|---|
--lib |
Build only this package's library |
--bins |
Build all binaries |
--bin [<NAME>] |
Build only the specified binary |
--examples |
Build all examples |
--example [<NAME>] |
Build only the specified example |
--tests |
Build all tests |
--test [<NAME>] |
Build only the specified test target |
--all-targets |
Build all targets |
-F, --features <FEATURES> |
Space or comma separated list of features to activate |
--all-features |
Activate all available features |
--no-default-features |
Do not activate the default feature |
-r, --release |
Build artifacts in release mode, with optimizations |
-j, --jobs <N> |
Number of parallel jobs, defaults to # of CPUs. |
cargo check
Check a local package and all of its dependencies for errors
cargo clean
Remove artifacts that cargo has generated in the past
Usage: cargo clean
cargo clippy
Checks a package to catch common mistakes and improve your Rust code.
Options
Option | Description |
---|---|
--no-deps |
Run Clippy only on the given crate, without linting the dependencies |
--fix |
Automatically apply lint suggestions. This flag implies --no-deps and --all-targets |
--explain LINT |
Print the documentation for a given lint |
To allow or deny a lint from the command line you can use cargo clippy --
with:
Option | Description |
---|---|
-W --warn OPT |
Set lint warnings |
-A --allow OPT |
Set lint allowed |
-D --deny OPT |
Set lint denied |
-F --forbid OPT |
Set lint forbidden |
cargo doc
Build a package's documentation
Options
Option | Description |
---|---|
--open |
Opens the docs in a browser after the operation |
--no-deps |
Don't build documentation for dependencies |
--document-private-items |
Document private items |
cargo fetch
Fetch dependencies of a package from the network
cargo fmt
Formats all bin and lib files of the current crate using rustfmt.
Usage: cargo fmt [--check]
cargo init
Create a new cargo package in an existing directory
Options
Option | Description |
---|---|
--bin |
Use a binary (application) template [default] |
--lib |
Use a library template |
--edition <YEAR> |
Edition to set for the crate generated [possible values: 2015, 2018, 2021] |
--name <NAME> |
Set the resulting package name, defaults to the directory name |
cargo install
Install a Rust binary. Default location is $HOME/.cargo/bin
Options
Option | Description |
---|---|
--version <VERSION> |
Specify a version to install |
--index <INDEX> |
Registry index to install from |
--registry <REGISTRY> |
Registry to use |
--git <URL> |
Git URL to install the specified crate from |
--branch <BRANCH> |
Branch to use when installing from git |
--tag <TAG> |
Tag to use when installing from git |
--rev <SHA> |
Specific commit to use when installing from git |
--path <PATH> |
Filesystem path to local crate to install |
--root <DIR> |
Directory to install packages into |
-f, --force |
Force overwriting existing crates or binaries |
--no-track |
Do not save tracking information |
--list |
list all installed packages and their versions |
-q, --quiet |
Do not print cargo log messages |
-v, --verbose... |
Use verbose output (-vv very verbose/build.rs output) |
--bin [<NAME>] |
Install only the specified binary |
--bins |
Install all binaries |
--example [<NAME>] |
Install only the specified example |
--examples |
Install all examples |
cargo login
Log in to a registry.
Usage: cargo login --registry registry <token>
cargo logout
Remove an API token from the registry locally.
Usage: cargo logout --registry reg
cargo new
Create a new cargo package
Options
Option | Description |
---|---|
--bin |
Use a binary (application) template [default] |
--lib |
Use a library template |
--edition <YEAR> |
Edition to set for the crate generated [possible values: 2015, 2018, 2021] |
--name <NAME> |
Set the resulting package name, defaults to the directory name |
cargo package
Assemble the local package into a distributable tarball
Options
Option | Description |
---|---|
-l, --list |
Print files included in a package without making one |
--no-verify |
Don't verify the contents by building them |
--no-metadata |
Ignore warnings about a lack of human-usable metadata |
--allow-dirty |
Allow dirty working directories to be packaged |
-q, --quiet |
Do not print cargo log messages |
-v, --verbose... |
Use verbose output (-vv very verbose/build.rs output) |
cargo publish
Upload a package to the registry
Options
Option | Description |
---|---|
--dry-run |
Perform all checks without uploading |
--index <INDEX> |
Registry index URL to upload the package to |
--registry <REGISTRY> |
Registry to publish to |
--token <TOKEN> |
Token to use when uploading |
--no-verify |
Don't verify the contents by building them |
--allow-dirty |
Allow dirty working directories to be packaged |
-q, --quiet |
Do not print cargo log messages |
-v, --verbose... |
Use verbose output (-vv very verbose/build.rs output) |
cargo metadata
Print a JSON representation of a Cargo.toml
manifest.
Usage: cargo metadata --no-deps
cargo remove
Remove dependencies from a Cargo.toml
manifest file
Options
Option | Description |
---|---|
--dry-run |
Don't actually write the manifest |
--dev |
Remove as development dependency |
--build |
Remove as build dependency |
--target <TARGET> |
Remove as dependency from the given target platform |
cargo run
Run a binary or example of the local package
Options
Option | Description |
---|---|
--bin <NAME> |
Name of the bin target to run |
--example <NAME> |
Name of the example target to run |
-F, --features <FEATURES> |
Space or comma separated list of features to activate |
--all-features |
Activate all available features |
--no-default-features |
Do not activate the default feature |
-j, --jobs <N> |
Number of parallel jobs, defaults to # of CPUs |
-r, --release |
Build artifacts in release mode, with optimizations |
cargo search
Search packages in registry.
Usage: cargo search [--registry registry] [--limit limit] package
cargo test
Execute all unit and integration tests and build examples of a local package
cargo tree
Display a tree visualization of a dependency graph
cargo uninstall
Remove a Rust binary
cargo update
Update dependencies as recorded in the local lock file
Usage: cargo update [--dry-run]
cargo flamegraph
You can generate flamegraphs for your rust project with this project.
Install with cargo install flamegraph
.
If you use mold
or ldd, you have to add this:
lld:
[target.x86_64-unknown-linux-gnu]
linker = "/usr/bin/clang"
rustflags = ["-Clink-arg=-fuse-ld=lld", "-Clink-arg=-Wl,--no-rosegment"]
mold:
[target.x86_64-unknown-linux-gnu]
linker = "clang"
rustflags = ["-Clink-arg=-fuse-ld=/usr/local/bin/mold", "-Clink-arg=-Wl,--no-rosegment"]
Usage: cargo flamegraph [OPTIONS] [-- <TRAILING_ARGUMENTS>...]
Options
Option | Description |
---|---|
--dev |
Build with the dev profile |
--profile <PROFILE> |
Build with the specified profile |
-p, --package <PACKAGE> |
package with the binary to run |
-b, --bin <BIN> |
Binary to run |
--example <EXAMPLE> |
Example to run |
--test <TEST> |
Test binary to run (currently profiles the test harness and all tests in the binary) |
--unit-test [<UNIT_TEST>] |
Crate target to unit test, may be omitted if crate only has one target (currently profiles the test harness and all tests in the binary; test selection can be passed as trailing arguments after -- as separator) |
--bench <BENCH> |
Benchmark to run |
--manifest-path <MANIFEST_PATH> |
Path to Cargo.toml |
-f, --features <FEATURES> |
Build features to enable |
--no-default-features |
Disable default features |
-r, --release |
No-op. For compatibility with cargo run --release |
-o, --output <OUTPUT> |
Output file [default: flamegraph.svg] |
--open |
Open the output .svg file with default program |
--root |
Run with root privileges (using sudo ) |
-F, --freq <FREQUENCY> |
Sampling frequency in Hz [default: 997] |
-c, --cmd <CUSTOM_CMD> |
Custom command for invoking perf/dtrace |
--deterministic |
Colors are selected such that the color of a function does not change between runs |
-i, --inverted |
Plot the flame graph up-side-down |
--reverse |
Generate stack-reversed flame graph |
--notes <STRING> |
Set embedded notes in SVG |
--min-width <FLOAT> |
Omit functions smaller than pixels [default: 0.01] |
--image-width <IMAGE_WIDTH> |
Image width in pixels |
--palette <PALETTE> |
Color palette [possible values: hot, mem, io, red, green, blue, aqua, yellow, purple, orange, wakeup, java, perl, js, rust] |
--skip-after <FUNCTION> |
Cut off stack frames below ; may be repeated |
--flamechart |
Produce a flame chart (sort by time, do not merge stacks) |
--ignore-status |
Ignores perf's exit code |
--no-inline |
Disable inlining for perf script because of performance issues |
--post-process <POST_PROCESS> |
Run a command to process the folded stacks, taking the input from stdin and outputting to stdout |
Manifest
The Cargo.toml
file for each package is called its manifest. It is written in the TOML format. It contains metadata that is needed to compile the package.
The [package]
section
The first section in a Cargo.toml is [package].
[package]
name = "hello_world" # the name of the package
version = "0.1.0" # the current version, obeying semver
authors = ["Alice <a@example.com>", "Bob <b@example.com>"]
The name
field
The package name is an identifier used to refer to the package. It is used when listed as a dependency in another package, and as the default name of inferred lib and bin targets.
The version
field
Cargo bakes in the concept of Semantic Versioning, so make sure you follow some basic rules:
- Before you reach
1.0.0
, anything goes, but if you make breaking changes, increment the minor version. In Rust, breaking changes include adding fields to structs or variants to enums. - After
1.0.0
, only make breaking changes when you increment the major version. Don’t break the build. - After
1.0.0
, don’t add any new public API (no new pub anything) in patch-level versions. Always increment the minor version if you add any new pub structs, traits, fields, types, functions, methods or anything else. - Use version numbers with three numeric parts such as
1.0.0
rather than1.0
.
This field is optional and defaults to 0.0.0
. The field is required for publishing packages.
The authors
field
The optional authors field lists in an array the people or organizations that are considered the “authors” of the package. The exact meaning is open to interpretation — it may list the original or primary authors, current maintainers, or owners of the package. An optional email address may be included within angled brackets at the end of each author entry.
[package]
# ...
authors = ["Graydon Hoare", "Fnu Lnu <no-reply@rust-lang.org>"]
This field is only surfaced in package metadata and in the $CARGO_PKG_AUTHORS
environment variable within build.rs
. It is not displayed in the crates.io user interface.
Warning
: Package manifests cannot be changed once published, so this field cannot be changed or removed in already-published versions of a package.
The edition
field
The edition key is an optional key that affects which Rust Edition your package is compiled with. Setting the edition key in [package]
will affect all targets/crates in the package, including test suites, benchmarks, binaries, examples, etc.
[package]
# ...
edition = '2021'
Most manifests have the edition field filled in automatically by cargo new
with the latest stable edition. By default cargo new
creates a manifest with the 2021 edition currently.
If the edition field is not present in Cargo.toml
, then the 2015 edition is assumed for backwards compatibility. Note that all manifests created with cargo new
will not use this historical fallback because they will have edition explicitly specified to a newer value.
The description
field
The description is a short blurb about the package. crates.io will display this with your package. This should be plain text (not Markdown).
[package]
# ...
description = "A short description of my package"
Note
: crates.io requires the description to be set.
The documentation
field
The documentation field specifies a URL to a website hosting the crate’s documentation. If no URL is specified in the manifest file, crates.io will automatically link your crate to the corresponding docs.rs page when the documentation has been built and is available.
[package]
# ...
documentation = "https://docs.rs/bitflags"
The readme
field
The readme field should be the path to a file in the package root (relative to this Cargo.toml
) that contains general information about the package. This file will be transferred to the registry when you publish. crates.io will interpret it as Markdown and render it on the crate’s page.
[package]
# ...
readme = "README.md"
If no value is specified for this field, and a file named README.md
, README.txt
or README
exists in the package root, then the name of that file will be used. You can suppress this behavior by setting this field to false. If the field is set to true, a default value of README.md
will be assumed.
The homepage
field
The homepage field should be a URL to a site that is the home page for your package.
[package]
# ...
homepage = "https://serde.rs"
A value should only be set for homepage if there is a dedicated website for the crate other than the source repository or API documentation. Do not make homepage redundant with either the documentation or repository values.
The repository
field
The repository field should be a URL to the source repository for your package.
[package]
# ...
repository = "https://github.com/rust-lang/cargo"
The license
and license-file
fields
The license field contains the name of the software license that the package is released under. The license-file field contains the path to a file containing the text of the license (relative to this Cargo.toml
).
crates.io interprets the license field as an SPDX 2.3 license expression. The name must be a known license from the SPDX license list 3.20. See the SPDX site for more information.
SPDX license expressions support AND and OR operators to combine multiple licenses.
[package]
# ...
license = "MIT OR Apache-2.0"
Using OR indicates the user may choose either license. Using AND indicates the user must comply with both licenses simultaneously. The WITH operator indicates a license with a special exception. Some examples:
- MIT OR Apache-2.0
- LGPL-2.1-only AND MIT AND BSD-2-Clause
- GPL-2.0-or-later WITH Bison-exception-2.2
If a package is using a nonstandard license, then the license-file field may be specified in lieu of the license field.
[package]
# ...
license-file = "LICENSE.txt"
Note
: crates.io requires either
license
orlicense-file
to be set.
The keywords
field
The keywords field is an array of strings that describe this package. This can help when searching for the package on a registry, and you may choose any words that would help someone find this crate.
[package]
# ...
keywords = ["gamedev", "graphics"]
Note
: crates.io allows a maximum of 5 keywords. Each keyword must be ASCII text, have at most 20 characters, start with an alphanumeric character, and only contain letters, numbers, _, - or +.
The categories
field
The categories field is an array of strings of the categories this package belongs to.
categories = ["command-line-utilities", "development-tools::cargo-plugins"]
Note
: crates.io has a maximum of 5 categories. Each category should match one of the strings available at https://crates.io/category_slugs, and must match exactly.
The workspace
field
The workspace field can be used to configure the workspace that this package will be a member of. If not specified this will be inferred as the first Cargo.toml
with [workspace]
upwards in the filesystem. Setting this is useful if the member is not inside a subdirectory of the workspace root.
[package]
# ...
workspace = "path/to/workspace/root"
This field cannot be specified if the manifest already has a [workspace]
table defined. That is, a crate cannot both be a root crate in a workspace (contain [workspace]
) and also be a member crate of another workspace (contain package.workspace
).
The build
field
The build field specifies a file in the package root which is a build script for building native code.
[package]
# ...
build = "build.rs"
The default is build.rs
, which loads the script from a file named build.rs
in the root of the package. Use build = "custom_build_name.rs"
to specify a path to a different file or build = false to disable automatic detection of the build script.
The links
field
The links field specifies the name of a native library that is being linked to.
For example, a crate that links a native library called “git2” (e.g. libgit2.a
on Linux) may specify:
[package]
# ...
links = "git2"
The exclude
and include
fields
The exclude and include fields can be used to explicitly specify which files are included when packaging a project to be published, and certain kinds of change tracking. The patterns specified in the exclude field identify a set of files that are not included, and the patterns in include specify files that are explicitly included. You may run cargo package --list
to verify which files will be included in the package.
[package]
# ...
exclude = ["/ci", "images/", ".*"]
[package]
# ...
include = ["/src", "COPYRIGHT", "/examples", "!/examples/big_example"]
The publish
field
The publish field can be used to control which registries names the package may be published to:
[package]
# ...
publish = ["some-registry-name"]
To prevent a package from being published to a registry (like crates.io) by mistake, for instance to keep a package private in a company, you can omit the version field. If you’d like to be more explicit, you can disable publishing:
[package]
# ...
publish = false
If publish array contains a single registry, cargo publish
command will use it when --registry
flag is not specified.
The metadata
table
Cargo by default will warn about unused keys in Cargo.toml
to assist in detecting typos and such. The package.metadata
table, however, is completely ignored by Cargo and will not be warned about. This section can be used for tools which would like to store package configuration in Cargo.toml
. For example:
[package]
name = "..."
# ...
# Metadata used when generating an Android APK, for example.
[package.metadata.android]
package-name = "my-awesome-android-app"
assets = "path/to/static"
Dependencies
Your crates can depend on other libraries from crates.io or other registries, git repositories, or subdirectories on your local file system.
Cargo is configured to look for dependencies on crates.io by default. Only the name and a version string are required in this case:
[dependencies]
time = "0.1.12"
The string 0.1.12
is a version requirement. Although it looks like a specific version of the time crate, it actually specifies a range of versions and allows SemVer compatible updates. An update is allowed if the new version number does not modify the left-most non-zero number in the major, minor, patch grouping. In this case, if we ran cargo update time
, cargo should update us to version 0.1.13
if it is the latest 0.1.z
release, but would not update us to 0.2.0
. If instead we had specified the version string as 1.0
, cargo should update to 1.1
if it is the latest 1.y
release, but not 2.0
. The version 0.0.x
is not considered compatible with any other version.
Specifying dependencies from other registries
To specify a dependency from a registry other than crates.io set the registry key to the name of the registry to use:
[dependencies]
some-crate = { version = "1.0", registry = "my-registry" }
where my-registry
is the registry name configured in .cargo/config.toml
file.
Note
: crates.io does not allow packages to be published with dependencies on code published outside of crates.io.
Specifying dependencies from git repositories
To depend on a library located in a git repository, the minimum information you need to specify is the location of the repository with the git key:
[dependencies]
regex = { git = "https://github.com/rust-lang/regex.git" }
Cargo fetches the git repository at that location and traverses the file tree to find Cargo.toml
file for the requested crate anywhere inside the git repository. For example, regex-lite and regex-syntax are members of rust-lang/regex repo and can be referred to by the repo’s root URL (https://github.com/rust-lang/regex.git) regardless of where in the file tree they reside.
regex-lite = { git = "https://github.com/rust-lang/regex.git" }
regex-syntax = { git = "https://github.com/rust-lang/regex.git" }
Choice of commit
Cargo assumes that we intend to use the latest commit on the default branch to build our package if we only specify the repo URL, as in the examples above.
You can combine the git
key with the rev
, tag
, or branch
keys to be more specific about which commit to use. Here’s an example of using the latest commit on a branch named next:
[dependencies]
regex = { git = "https://github.com/rust-lang/regex.git", branch = "next" }
Anything that is not a branch or a tag falls under rev key. This can be a commit hash like rev = "4c59b707"
, or a named reference exposed by the remote repository such as rev = "refs/pull/493/head"
.
What references are available for the rev
key varies by where the repo is hosted.
More git dependency examples:
# .git suffix can be omitted if the host accepts such URLs - both examples work the same
regex = { git = "https://github.com/rust-lang/regex" }
regex = { git = "https://github.com/rust-lang/regex.git" }
# a commit with a particular tag
regex = { git = "https://github.com/rust-lang/regex.git", tag = "1.10.3" }
# a commit by its SHA1 hash
regex = { git = "https://github.com/rust-lang/regex.git", rev = "0c0990399270277832fbb5b91a1fa118e6f63dba" }
# HEAD commit of PR 493
regex = { git = "https://github.com/rust-lang/regex.git", rev = "refs/pull/493/head" }
# INVALID EXAMPLES
# specifying the commit after # ignores the commit ID and generates a warning
regex = { git = "https://github.com/rust-lang/regex.git#4c59b70" }
# git and path cannot be used at the same time
regex = { git = "https://github.com/rust-lang/regex.git#4c59b70", path = "../regex" }
Cargo locks the commits of git dependencies in Cargo.lock
file at the time of their addition and checks for updates only when you run cargo update
command.
The role of the version key
The version
key always implies that the package is available in a registry, regardless of the presence of git
or path
keys.
The version
key does not affect which commit is used when Cargo retrieves the git dependency, but Cargo checks the version information in the dependency’s Cargo.toml
file against the version
key and raises an error if the check fails.
In this example, Cargo retrieves the HEAD commit of the branch called next from Git and checks if the crate’s version is compatible with version = "1.10.3"
:
[dependencies]
regex = { version = "1.10.3", git = "https://github.com/rust-lang/regex.git", branch = "next" }
version
, git
, and path
keys are considered separate locations for resolving the dependency.
Specifying path dependencies
Cargo supports path dependencies which are typically sub-crates that live within one repository.
[dependencies]
hello_utils = { path = "hello_utils" }
This tells Cargo that we depend on a crate called hello_utils
which is found in the hello_utils
folder, relative to the Cargo.toml
file it’s written in.
The next cargo build
will automatically build hello_utils
and all of its dependencies.
The local paths must point to the exact folder with the dependency’s Cargo.toml. Unlike with git dependencies, Cargo does not traverse local paths. For example, if regex-lite and regex-syntax are members of a locally cloned rust-lang/regex repo, they have to be referred to by the full path:
# git key accepts the repo root URL and Cargo traverses the tree to find the crate
[dependencies]
regex-lite = { git = "https://github.com/rust-lang/regex.git" }
regex-syntax = { git = "https://github.com/rust-lang/regex.git" }
# path key requires the member name to be included in the local path
[dependencies]
regex-lite = { path = "../regex/regex-lite" }
regex-syntax = { path = "../regex/regex-syntax" }
Local paths in published crates
Crates that use dependencies specified with only a path are not permitted on crates.io.
Multiple locations
It is possible to specify both a registry version and a git or path location. The git or path dependency will be used locally (in which case the version is checked against the local copy), and when published to a registry like crates.io, it will use the registry version. Other combinations are not allowed. Examples:
[dependencies]
# Uses `my-bitflags` when used locally, and uses
# version 1.0 from crates.io when published.
bitflags = { path = "my-bitflags", version = "1.0" }
# Uses the given git repo when used locally, and uses
# version 1.0 from crates.io when published.
smallvec = { git = "https://github.com/servo/rust-smallvec.git", version = "1.0" }
Platform specific dependencies
Platform-specific dependencies take the same format, but are listed under a target section. Normally Rust-like #[cfg]
syntax will be used to define these sections:
[target.'cfg(windows)'.dependencies]
winhttp = "0.4.0"
[target.'cfg(unix)'.dependencies]
openssl = "1.0.1"
[target.'cfg(target_arch = "x86")'.dependencies]
native-i686 = { path = "native/i686" }
[target.'cfg(target_arch = "x86_64")'.dependencies]
native-x86_64 = { path = "native/x86_64" }
Like with Rust, the syntax here supports the not
, any
, and all
operators to combine various cfg
name/value pairs.
If you want to know which cfg targets are available on your platform, run rustc --print=cfg
from the command line. If you want to know which cfg targets are available for another platform, such as 64-bit Windows, 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 instead:
[dependencies]
foo = { version = "1.0", optional = true }
bar = { version = "1.0", optional = true }
[features]
fancy-feature = ["foo", "bar"]
The same applies to cfg(debug_assertions)
, cfg(test)
and cfg(proc_macro)
. These values will not work as expected and will always have the default value returned by rustc --print=cfg
. There is currently no way to add dependencies based on these configuration values.
In addition to #[cfg]
syntax, Cargo also supports listing out the full target the dependencies would apply to:
[target.x86_64-pc-windows-gnu.dependencies]
winhttp = "0.4.0"
[target.i686-unknown-linux-gnu.dependencies]
openssl = "1.0.1"
Custom target specifications
If you’re using a custom target specification (such as --target foo/bar.json
), use the base filename without the .json extension:
[target.bar.dependencies]
winhttp = "0.4.0"
[target.my-special-i686-platform.dependencies]
openssl = "1.0.1"
native = { path = "native/i686" }
Development dependencies
You can add a [dev-dependencies]
section to your Cargo.toml
whose format is equivalent to [dependencies]
:
[dev-dependencies]
tempdir = "0.3"
Dev-dependencies are not used when compiling a package for building, but are used for compiling tests, examples, and benchmarks.
These dependencies are not propagated to other packages which depend on this package.
You can also have target-specific development dependencies by using dev-dependencies in the target section header instead of dependencies. For example:
[target.'cfg(unix)'.dev-dependencies]
mio = "0.0.1"
Build dependencies
You can depend on other Cargo-based crates for use in your build scripts. Dependencies are declared through the build-dependencies
section of the manifest:
[build-dependencies]
cc = "1.0.3"
You can also have target-specific build dependencies by using build-dependencies in the target section header instead of dependencies. For example:
[target.'cfg(unix)'.build-dependencies]
cc = "1.0.3"
In this case, the dependency will only be built when the host platform matches the specified target.
The build script does not have access to the dependencies listed in the dependencies
or dev-dependencies
section. Build dependencies will likewise not be available to the package itself unless listed under the dependencies section as well. A package itself and its build script are built separately, so their dependencies need not coincide. Cargo is kept simpler and cleaner by using independent dependencies for independent purposes.
Choosing features
If a package you depend on offers conditional features, you can specify which to use:
[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"]
Renaming dependencies in Cargo.toml
When writing a [dependencies]
section in Cargo.toml
the key you write for a dependency typically matches up to the name of the crate you import from in the code. For some projects, though, you may wish to reference the crate with a different name in the code regardless of how it’s published on crates.io. For example you may wish to:
- Avoid the need to
use foo as bar
in Rust source. - Depend on multiple versions of a crate.
- Depend on crates with the same name from different registries.
To support this Cargo supports a package key in the [dependencies]
section of which package should be depended on:
[package]
name = "mypackage"
version = "0.0.1"
[dependencies]
foo = "0.1"
bar = { git = "https://github.com/example/project.git", package = "foo" }
baz = { version = "0.1", registry = "custom", package = "foo" }
In this example, three crates are now available in your Rust code:
extern crate foo; // crates.io
extern crate bar; // git repository
extern crate baz; // registry `custom`
All three of these crates have the package name of foo in their own Cargo.toml
, so we’re explicitly using the package key to inform Cargo that we want the foo package even though we’re calling it something else locally. The package key, if not specified, defaults to the name of the dependency being requested.
Note that if you have an optional dependency like:
[dependencies]
bar = { version = "0.1", package = 'foo', optional = true }
you’re depending on the crate foo from crates.io, but your crate has a bar feature instead of a foo feature. That is, names of features take after the name of the dependency, not the package name, when renamed.
Enabling transitive dependencies works similarly, for example we could add the following to the above manifest:
[features]
log-debug = ['bar/log-debug'] # using 'foo/log-debug' would be an error!
The [lints]
section
Override the default level of lints from different tools by assigning them to a new level in a table, for example:
[lints.rust]
unsafe_code = "forbid"
This is short-hand for:
[lints.rust]
unsafe_code = { level = "forbid", priority = 0 }
level corresponds to the lint levels in rustc:
forbid
deny
warn
allow
priority is a signed integer that controls which lints or lint groups override other lint groups. lower (particularly negative) numbers have lower priority, being overridden by higher numbers, and show up first on the command-line to tools like rustc
To know which table under [lints]
a particular lint belongs under, it is the part before ::
in the lint name. If there isn’t a ::
, then the tool is rust
. For example a warning about unsafe_code
would be lints.rust.unsafe_code
but a lint about clippy::enum_glob_use
would be lints.clippy.enum_glob_use
.
For example:
[lints.rust]
unsafe_code = "forbid"
[lints.clippy]
enum_glob_use = "deny"
Cargo Targets
Cargo packages consist of targets which correspond to source files which can be compiled into a crate. Packages can have library, binary, example, test, and benchmark targets. The list of targets can be configured in the Cargo.toml
manifest, often inferred automatically by the directory layout of the source files.
Library
The library target defines a “library” that can be used and linked by other libraries and executables. The filename defaults to src/lib.rs
, and the name of the library defaults to the name of the package, with any dashes replaced with underscores. A package can have only one library. The settings for the library can be customized in the [lib]
table in Cargo.toml
.
# Example of customizing the library in Cargo.toml.
[lib]
crate-type = ["cdylib"]
bench = false
Binaries
Binary targets are executable programs that can be run after being compiled. The default binary filename is src/main.rs
, which defaults to the name of the package. Additional binaries are stored in the src/bin/
directory. The settings for each binary can be customized in the [[bin]]
tables in Cargo.toml
.
Binaries can use the public API of the package’s library. They are also linked with the [dependencies]
defined in Cargo.toml
.
You can run individual binaries with the cargo run
command with the --bin <bin-name>
option. cargo install
can be used to copy the executable to a common location.
# Example of customizing binaries in Cargo.toml.
[[bin]]
name = "cool-tool"
test = false
bench = false
[[bin]]
name = "frobnicator"
required-features = ["frobnicate"]
Examples
Files located under the examples directory are example uses of the functionality provided by the library. When compiled, they are placed in the target/debug/examples
directory.
Examples can use the public API of the package’s library. They are also linked with the [dependencies]
and [dev-dependencies]
defined in Cargo.toml
.
By default, examples are executable binaries (with a main()
function). You can specify the crate-type field to make an example be compiled as a library:
[[example]]
name = "foo"
crate-type = ["staticlib"]
You can run individual executable examples with the cargo run
command with the --example <example-name>
option. Library examples can be built with cargo build
with the --example <example-name>
option. cargo install
with the --example <example-name>
option can be used to copy executable binaries to a common location. Examples are compiled by cargo test
by default to protect them from bit-rotting. Set the test field to true if you have #[test]
functions in the example that you want to run with cargo test
.
Tests
There are two styles of tests within a Cargo project:
- Unit tests which are functions marked with the
#[test]
attribute located within your library or binaries (or any target enabled with the test field). These tests have access to private APIs located within the target they are defined in. - Integration tests which is a separate executable binary, also containing
#[test]
functions, which is linked with the project’s library and has access to its public API.
Tests are run with the cargo test
command. By default, Cargo and rustc use the libtest harness which is responsible for collecting functions annotated with the #[test]
attribute and executing them in parallel, reporting the success and failure of each test. See the harness field if you want to use a different harness or test strategy.
Note
: There is another special style of test in Cargo: documentation tests. They are handled by rustdoc and have a slightly different execution model.
Integration tests
Files located under the tests
directory are integration tests. When you run cargo test
, Cargo will compile each of these files as a separate crate, and execute them.
Integration tests can use the public API of the package’s library. They are also linked with the [dependencies]
and [dev-dependencies]
defined in Cargo.toml
.
If you want to share code among multiple integration tests, you can place it in a separate module such as tests/common/mod.rs
and then put mod common
; in each test to import it.
Each integration test results in a separate executable binary, and cargo test
will run them serially. In some cases this can be inefficient, as it can take longer to compile, and may not make full use of multiple CPUs when running the tests. If you have a lot of integration tests, you may want to consider creating a single integration test, and split the tests into multiple modules. The libtest harness will automatically find all of the #[test]
annotated functions and run them in parallel. You can pass module names to cargo test
to only run the tests within that module.
Benchmarks
Benchmarks provide a way to test the performance of your code using the cargo bench
command. They follow the same structure as tests, with each benchmark function annotated with the #[bench]
attribute. Similarly to tests:
- Benchmarks are placed in the
benches
directory. - Benchmark functions defined in libraries and binaries have access to the private API within the target they are defined in. Benchmarks in the benches directory may use the public API.
- The bench field can be used to define which targets are benchmarked by default.
- The harness field can be used to disable the built-in harness.
Note
: The
#[bench]
attribute is currently unstable and only available on the nightly channel. There are some packages available on crates.io that may help with running benchmarks on the stable channel, such as Criterion.
Configuring a target
All of the [lib]
, [[bin]]
, [[example]]
, [[test]]
, and [[bench]]
sections in Cargo.toml
support similar configuration for specifying how a target should be built. The double-bracket sections like [[bin]]
are array-of-table of TOML, which means you can write more than one [[bin]]
section to make several executables in your crate. You can only specify one library, so [lib]
is a normal TOML table.
The following is an overview of the TOML settings for each target.
[lib]
name = "foo" # The name of the target.
path = "src/lib.rs" # The source file of the target.
test = true # Is tested by default.
doctest = true # Documentation examples are tested by default.
bench = true # Is benchmarked by default.
doc = true # Is documented by default.
plugin = false # Used as a compiler plugin (deprecated).
proc-macro = false # Set to `true` for a proc-macro library.
harness = true # Use libtest harness.
edition = "2015" # The edition of the target.
crate-type = ["lib"] # The crate types to generate.
required-features = [] # Features required to build this target (N/A for lib).
Features
Cargo “features” provide a mechanism to express conditional compilation and optional dependencies. A package defines a set of named features in the [features]
table of Cargo.toml
, and each feature can either be enabled or disabled. Features for the package being built can be enabled on the command-line with flags such as --features
. Features for dependencies can be enabled in the dependency declaration in Cargo.toml
.
The [features]
section
Features are defined in the [features]
table in Cargo.toml. Each feature specifies an array of other features or optional dependencies that it enables. The following examples illustrate how features could be used for a 2D image processing library where support for different image formats can be optionally included:
[features]
# Defines a feature named `webp` that does not enable any other features.
webp = []
With this feature defined, cfg
expressions can be used to conditionally include code to support the requested feature at compile time. For example, inside lib.rs
of the package could include this:
// This conditionally includes a module which implements WEBP support.
#[cfg(feature = "webp")]
pub mod webp;
Cargo sets features in the package using the rustc --cfg
flag, and code can test for their presence with the cfg
attribute or the cfg
macro.
Features can list other features to enable. For example, the ICO image format can contain BMP and PNG images, so when it is enabled, it should make sure those other features are enabled, too:
[features]
bmp = []
png = []
ico = ["bmp", "png"]
webp = []
The default feature
By default, all features are disabled unless explicitly enabled. This can be changed by specifying the default feature:
[features]
default = ["ico", "webp"]
bmp = []
png = []
ico = ["bmp", "png"]
webp = []
When the package is built, the default feature is enabled which in turn enables the listed features. This behavior can be changed by:
- The
--no-default-features
command-line flag disables the default features of the package. - The
default-features = false
option can be specified in a dependency declaration.
Note
: Be careful about choosing the default feature set. The default features are a convenience that make it easier to use a package without forcing the user to carefully select which features to enable for common use, but there are some drawbacks. Dependencies automatically enable default features unless default-features = false is specified. This can make it difficult to ensure that the default features are not enabled, especially for a dependency that appears multiple times in the dependency graph. Every package must ensure that
default-features = false
is specified to avoid enabling them.
Optional dependencies
Dependencies can be marked “optional”, which means they will not be compiled by default. For example, let’s say that our 2D image processing library uses an external package to handle GIF images. This can be expressed like this:
[dependencies]
gif = { version = "0.11.1", optional = true }
By default, this optional dependency implicitly defines a feature that looks like this:
[features]
gif = ["dep:gif"]
This means that this dependency will only be included if the gif feature is enabled. The same cfg(feature = "gif")
syntax can be used in the code, and the dependency can be enabled just like any feature such as --features gif
.
In some cases, you may not want to expose a feature that has the same name as the optional dependency. For example, perhaps the optional dependency is an internal detail, or you want to group multiple optional dependencies together, or you just want to use a better name. If you specify the optional dependency with the dep:
prefix anywhere in the [features]
table, that disables the implicit feature.
For example, let’s say in order to support the AVIF image format, our library needs two other dependencies to be enabled.
[dependencies]
ravif = { version = "0.6.3", optional = true }
rgb = { version = "0.8.25", optional = true }
[features]
avif = ["dep:ravif", "dep:rgb"]
In this example, the avif feature will enable the two listed dependencies. This also avoids creating the implicit ravif and rgb features, since we don’t want users to enable those individually as they are internal details to our crate.
Note
: Another way to optionally include a dependency is to use platform-specific dependencies. Instead of using features, these are conditional based on the target platform.
Dependency features
Features of dependencies can be enabled within the dependency declaration. The features key indicates which features to enable.
[dependencies]
# Enables the `derive` feature of serde.
serde = { version = "1.0.118", features = ["derive"] }
The default features can be disabled using default-features = false
:
[dependencies]
flate2 = { version = "1.0.3", default-features = false, features = ["zlib"] }
Note
: This may not ensure the default features are disabled. If another dependency includes flate2 without specifying
default-features = false
, then the default features will be enabled.
Features of dependencies can also be enabled in the [features]
table. The syntax is "package-name/feature-name". For example:
[dependencies]
jpeg-decoder = { version = "0.1.20", default-features = false }
[features]
# Enables parallel processing support by enabling the "rayon" feature of jpeg-decoder.
parallel = ["jpeg-decoder/rayon"]
The "package-name/feature-name" syntax will also enable package-name if it is an optional dependency. Often this is not what you want. You can add a ?
as in "package-name?/feature-name" which will only enable the given feature if something else enables the optional dependency.
For example, let’s say we have added some serialization support to our library, and it requires enabling a corresponding feature in some optional dependencies. That can be done like this:
[dependencies]
serde = { version = "1.0.133", optional = true }
rgb = { version = "0.8.25", optional = true }
[features]
serde = ["dep:serde", "rgb?/serde"]
In this example, enabling the serde feature will enable the serde dependency. It will also enable the serde feature for the rgb dependency, but only if something else has enabled the rgb dependency.
Command-line feature options
The following command-line flags can be used to control which features are enabled:
--features FEATURES
: Enables the listed features. Multiple features may be separated with commas or spaces. If using spaces, be sure to use quotes around all the features if running Cargo from a shell (such as--features "foo bar"
). If building multiple packages in a workspace, the package-name/feature-name syntax can be used to specify features for specific workspace members.--all-features
: Activates all features of all packages selected on the command-line.--no-default-features
: Does not activate the default feature of the selected packages.
Mutually exclusive features
There are rare cases where features may be mutually incompatible with one another. This should be avoided if at all possible, because it requires coordinating all uses of the package in the dependency graph to cooperate to avoid enabling them together. If it is not possible, consider adding a compile error to detect this scenario. For example:
#[cfg(all(feature = "foo", feature = "bar"))]
compile_error!("feature \"foo\" and feature \"bar\" cannot be enabled at the same time");
Build scripts
Build scripts can detect which features are enabled on the package by inspecting the CARGO_FEATURE_<name>
environment variable, where <name>
is the feature name converted to uppercase and -
converted to _
.
Profiles
Profiles provide a way to alter the compiler settings, influencing things like optimizations and debugging symbols.
Cargo has 4 built-in profiles: dev
, release
, test
, and bench
. The profile is automatically chosen based on which command is being run if a profile is not specified on the command-line. In addition to the built-in profiles, custom user-defined profiles can also be specified.
Profile settings can be changed in Cargo.toml
with the [profile]
table. Within each named profile, individual settings can be changed with key/value pairs like this:
[profile.dev]
opt-level = 1 # Use slightly better optimizations.
overflow-checks = false # Disable integer overflow checks.
Cargo only looks at the profile settings in the Cargo.toml
manifest at the root of the workspace. Profile settings defined in dependencies will be ignored.
Additionally, profiles can be overridden from a config definition. Specifying a profile in a config file or environment variable will override the settings from Cargo.toml
.
Profile Settings
The following is a list of settings that can be controlled in a profile.
opt-level
The opt-level
setting controls the -C opt-level
flag which controls the level of optimization. Higher optimization levels may produce faster runtime code at the expense of longer compiler times. Higher levels may also change and rearrange the compiled code which may make it harder to use with a debugger.
The valid options are:
0
: no optimizations1
: basic optimizations2
: some optimizations3
: all optimizationss
: optimize for binary sizez
: optimize for binary size, but also turn off loop vectorization.
It is recommended to experiment with different levels to find the right balance for your project. There may be surprising results, such as level 3 being slower than 2, or the "s" and "z" levels not being necessarily smaller. You may also want to reevaluate your settings over time as newer versions of rustc change optimization behavior.
debug
The debug setting controls the -C debuginfo
flag which controls the amount of debug information included in the compiled binary.
The valid options are:
0
,false
, ornone
: no debug info at all, default for releaseline-directives-only
: line info directives only. For the nvptx* targets this enables profiling. For other use cases, line-tables-only is the better, more compatible choice.line-tables-only
: line tables only. Generates the minimal amount of debug info for backtraces with filename/line number info, but not anything else, i.e. no variable or function parameter info.1
orlimited
: debug info without type or variable-level information. Generates more detailed module-level info than line-tables-only.2
,true
, orfull
: full debug info, default for dev
split-debuginfo
The split-debuginfo
setting controls the -C split-debuginfo
flag which controls whether debug information, if generated, is either placed in the executable itself or adjacent to it.
strip
The strip
option controls the -C strip
flag, which directs rustc to strip either symbols or debuginfo from a binary. This can be enabled like so:
[package]
# ...
[profile.release]
strip = "debuginfo"
Possible string values of strip are none
, debuginfo
, and symbols
. The default is none
.
debug-assertions
The debug-assertions
setting controls the -C debug-assertions
flag which turns cfg(debug_assertions)
conditional compilation on or off. Debug assertions are intended to include runtime validation which is only available in debug/development builds. These may be things that are too expensive or otherwise undesirable in a release build. Debug assertions enables the debug_assert!
macro in the standard library.
overflow-checks
The overflow-checks
setting controls the -C overflow-checks
flag which controls the behavior of runtime integer overflow. When overflow-checks are enabled, a panic will occur on overflow.
lto
The lto
setting controls rustc’s -C lto
, -C linker-plugin-lto
, and -C embed-bitcode
options, which control LLVM’s link time optimizations. LTO can produce better optimized code, using whole-program analysis, at the cost of longer linking time.
The valid options are:
false
: Performs “thin local LTO” which performs “thin” LTO on the local crate only across its codegen units. No LTO is performed if codegen units is 1 or opt-level is 0.true
orfat
: Performs “fat” LTO which attempts to perform optimizations across all crates within the dependency graph.thin
: Performs “thin” LTO. This is similar to “fat”, but takes substantially less time to run while still achieving performance gains similar to “fat”.off
: Disables LTO.
panic
The panic
setting controls the -C panic
flag which controls which panic strategy to use.
The valid options are:
unwind
: Unwind the stack upon panic.abort
: Terminate the process upon panic.
incremental
The incremental
setting controls the -C incremental flag which controls whether or not incremental compilation is enabled. Incremental compilation causes rustc to save additional information to disk which will be reused when recompiling the crate, improving re-compile times. The additional information is stored in the target
directory.
codegen-units
The codegen-units
setting controls the -C codegen-units
flag which controls how many “code generation units” a crate will be split into. More code generation units allows more of a crate to be processed in parallel possibly reducing compile time, but may produce slower code.
This option takes an integer greater than 0.
The default is 256 for incremental builds, and 16 for non-incremental builds.
rpath
The rpath
setting controls the -C rpath
flag which controls whether or not rpath is enabled.
Default profiles
dev
The dev
profile is used for normal development and debugging. It is the default for build commands like cargo build
, and is used for cargo install --debug
.
The default settings for the dev
profile are:
[profile.dev]
opt-level = 0
debug = true
split-debuginfo = '...' # Platform-specific.
strip = "none"
debug-assertions = true
overflow-checks = true
lto = false
panic = 'unwind'
incremental = true
codegen-units = 256
rpath = false
release
The release
profile is intended for optimized artifacts used for releases and in production. This profile is used when the --release
flag is used, and is the default for cargo install
.
The default settings for the release
profile are:
[profile.release]
opt-level = 3
debug = false
split-debuginfo = '...' # Platform-specific.
strip = "none"
debug-assertions = false
overflow-checks = false
lto = false
panic = 'unwind'
incremental = false
codegen-units = 16
rpath = false
test
The test
profile is the default profile used by cargo test
. The test
profile inherits the settings from the dev
profile.
bench
The bench
profile is the default profile used by cargo bench
. The bench
profile inherits the settings from the release
profile.
Custom profiles
In addition to the built-in profiles, additional custom profiles can be defined. These may be useful for setting up multiple workflows and build modes. When defining a custom profile, you must specify the inherits key to specify which profile the custom profile inherits settings from when the setting is not specified.
For example, let’s say you want to compare a normal release build with a release build with LTO optimizations, you can specify something like the following in Cargo.toml
:
[profile.release-lto]
inherits = "release"
lto = true
The --profile
flag can then be used to choose this custom profile:
cargo build --profile release-lto
The output for each profile will be placed in a directory of the same name as the profile in the target
directory. As in the example above, the output would go into the target/release-lto
directory.
Build Scripts
Some packages need to compile third-party non-Rust code, for example C libraries. Other packages need to link to C libraries which can either be located on the system or possibly need to be built from source. Others still need facilities for functionality such as code generation before building (think parser generators).
Cargo does not aim to replace other tools that are well-optimized for these tasks, but it does integrate with them with custom build scripts. Placing a file named build.rs
in the root of a package will cause Cargo to compile that script and execute it just before building the package.
// Example custom build script.
fn main() {
// Tell Cargo that if the given file changes, to rerun this build script.
println!("cargo:rerun-if-changed=src/hello.c");
// Use the `cc` crate to build a C file and statically link it.
cc::Build::new()
.file("src/hello.c")
.compile("hello");
}
Environment Variables
When the build script is run, there are a number of inputs to the build script, all passed in the form of environment variables.
Cargo exposes these environment variables to your crate when it is compiled. Note that this applies for running binaries with cargo run
and cargo test
as well. To get the value of any of these variables in a Rust program, do this:
let version = env!("CARGO_PKG_VERSION");
Exposed environment variables:
CARGO
— Path to thecargo
binary performing the build.CARGO_MANIFEST_DIR
— The directory containing the manifest of your package.CARGO_PKG_VERSION
— The full version of your package.CARGO_PKG_VERSION_MAJOR
— The major version of your package.CARGO_PKG_VERSION_MINOR
— The minor version of your package.CARGO_PKG_VERSION_PATCH
— The patch version of your package.CARGO_PKG_VERSION_PRE
— The pre-release version of your package.CARGO_PKG_AUTHORS
— Colon separated list of authors from the manifest of your package.CARGO_PKG_NAME
— The name of your package.CARGO_PKG_DESCRIPTION
— The description from the manifest of your package.CARGO_PKG_HOMEPAGE
— The home page from the manifest of your package.CARGO_PKG_REPOSITORY
— The repository from the manifest of your package.CARGO_PKG_LICENSE
— The license from the manifest of your package.CARGO_PKG_LICENSE_FILE
— The license file from the manifest of your package.CARGO_PKG_RUST_VERSION
— The Rust version from the manifest of your package. Note that this is the minimum Rust version supported by the package, not the current Rust version.CARGO_PKG_README
— Path to the README file of your package.CARGO_CRATE_NAME
— The name of the crate that is currently being compiled. It is the name of the Cargo target with-
converted to_
, such as the name of the library, binary, example, integration test, or benchmark.CARGO_BIN_NAME
— The name of the binary that is currently being compiled. Only set for binaries or binary examples. This name does not include any file extension, such as.exe
.OUT_DIR
— If the package has a build script, this is set to the folder where the build script should place its output.CARGO_BIN_EXE_<name>
— The absolute path to a binary target’s executable. This is only set when building an integration test or benchmark. This may be used with theenv
macro to find the executable to run for testing purposes. The<name>
is the name of the binary target, exactly as-is. For example,CARGO_BIN_EXE_my-program
for a binary namedmy-program
. Binaries are automatically built when the test is built, unless the binary has required features that are not enabled.CARGO_PRIMARY_PACKAGE
— This environment variable will be set if the package being built is primary. Primary packages are the ones the user selected on the command-line, either with-p
flags or the defaults based on the current directory and the default workspace members. This environment variable will not be set when building dependencies. This is only set when compiling the package (not when running binaries or tests).CARGO_TARGET_TMPDIR
— Only set when building integration test or benchmark code. This is a path to a directory inside the target directory where integration tests or benchmarks are free to put any data needed by the tests/benches. Cargo initially creates this directory but doesn’t manage its content in any way, this is the responsibility of the test code.