]> git.proxmox.com Git - cargo.git/blame - ARCHITECTURE.md
drop patches applied upstream or in debcargo-conf
[cargo.git] / ARCHITECTURE.md
CommitLineData
00c17cc0
AK
1# Cargo Architecture
2
3This document gives a high level overview of Cargo internals. You may
4find it useful if you want to contribute to Cargo or if you are
5interested in the inner workings of Cargo.
6
37a64d4d 7The purpose of Cargo is to formalize a canonical Rust workflow, by automating
f7c91ba6 8the standard tasks associated with distributing software. Cargo simplifies
37a64d4d
DW
9structuring a new project, adding dependencies, writing and running unit tests,
10and more.
11
00c17cc0
AK
12
13## Subcommands
14
c2cd0fde 15Cargo is a single binary composed of a set of [`clap`] subcommands. All subcommands live in
0c9e2b1b 16`src/bin/cargo/commands` directory. `src/bin/cargo/main.rs` is the entry point.
00c17cc0 17
c2cd0fde 18Each subcommand, such as [`src/bin/cargo/commands/build.rs`], has its own API
37a64d4d
DW
19interface, similarly to Git's, parsing command line options, reading the
20configuration files, discovering the Cargo project in the current directory and
21delegating the actual implementation to one
c2cd0fde 22of the functions in [`src/cargo/ops/mod.rs`]. This short file is a good
00c17cc0 23place to find out about most of the things that Cargo can do.
37a64d4d
DW
24Subcommands are designed to pipe to one another, and custom subcommands make
25Cargo easy to extend and attach tools to.
26
27[`clap`]: https://clap.rs/
fea514a5
HY
28[`src/bin/cargo/commands/build.rs`]: src/bin/cargo/commands/build.rs
29[`src/cargo/ops/mod.rs`]: src/cargo/ops/mod.rs
00c17cc0
AK
30
31
32## Important Data Structures
33
34There are some important data structures which are used throughout
35Cargo.
36
c2cd0fde 37[`Config`] is available almost everywhere and holds "global"
00c17cc0 38information, such as `CARGO_HOME` or configuration from
c2cd0fde 39`.cargo/config` files. The [`shell`] method of [`Config`] is the entry
00c17cc0
AK
40point for printing status messages and other info to the console.
41
c2cd0fde 42[`Workspace`] is the description of the workspace for the current
00c17cc0 43working directory. Each workspace contains at least one
c2cd0fde
HY
44[`Package`]. Each package corresponds to a single `Cargo.toml`, and may
45define several [`Target`]s, such as the library, binaries, integration
00c17cc0
AK
46test or examples. Targets are crates (each target defines a crate
47root, like `src/lib.rs` or `examples/foo.rs`) and are what is actually
48compiled by `rustc`.
49
50A typical package defines the single library target and several
51auxiliary ones. Packages are a unit of dependency in Cargo, and when
52package `foo` depends on package `bar`, that means that each target
53from `foo` needs the library target from `bar`.
54
c2cd0fde 55[`PackageId`] is the unique identifier of a (possibly remote)
00c17cc0
AK
56package. It consist of three components: name, version and source
57id. Source is the place where the source code for package comes
58from. Typical sources are crates.io, a git repository or a folder on
59the local hard drive.
60
c2cd0fde
HY
61[`Resolve`] is the representation of a directed acyclic graph of package
62dependencies, which uses [`PackageId`]s for nodes. This is the data
f7c91ba6 63structure that is saved to the lock file. If there is no lock file,
00c17cc0
AK
64Cargo constructs a resolve by finding a graph of packages which
65matches declared dependency specification according to semver.
66
85c5fe1f
HY
67[`Config`]: https://docs.rs/cargo/latest/cargo/util/config/struct.Config.html
68[`shell`]: https://docs.rs/cargo/latest/cargo/util/config/struct.Config.html#method.shell
69[`Workspace`]: https://docs.rs/cargo/latest/cargo/core/struct.Workspace.html
70[`Package`]: https://docs.rs/cargo/latest/cargo/core/package/struct.Package.html
71[`Target`]: https://docs.rs/cargo/latest/cargo/core/manifest/struct.Target.html
72[`PackageId`]: https://docs.rs/cargo/latest/cargo/core/package_id/struct.PackageId.html
73[`Resolve`]: https://docs.rs/cargo/latest/cargo/core/struct.Resolve.html
c2cd0fde 74
00c17cc0
AK
75
76## Persistence
77
78Cargo is a non-daemon command line application, which means that all
79the information used by Cargo must be persisted on the hard drive. The
80main sources of information are `Cargo.toml` and `Cargo.lock` files,
81`.cargo/config` configuration files and the globally shared registry
82of packages downloaded from crates.io, usually located at
c2cd0fde 83`~/.cargo/registry`. See [`src/cargo/sources/registry`] for the specifics of
00c17cc0
AK
84the registry storage format.
85
fea514a5 86[`src/cargo/sources/registry`]: src/cargo/sources/registry
c2cd0fde 87
00c17cc0
AK
88
89## Concurrency
90
8495aa3f
AK
91Cargo is mostly single threaded. The only concurrency inside a single
92instance of Cargo happens during compilation, when several instances
93of `rustc` are invoked in parallel to build independent
94targets. However there can be several different instances of Cargo
95process running concurrently on the system. Cargo guarantees that this
96is always safe by using file locks when accessing potentially shared
97data like the registry or the target directory.
00c17cc0
AK
98
99
100## Tests
101
102Cargo has an impressive test suite located in the `tests` folder. Most
103of the test are integration: a project structure with `Cargo.toml` and
104rust source code is created in a temporary directory, `cargo` binary
105is invoked via `std::process::Command` and then stdout and stderr are
106verified against the expected output. To simplify testing, several
107macros of the form `[MACRO]` are used in the expected output. For
923d1836 108example, `[..]` matches any string.
005bd4b4 109
c083880c
DW
110To see stdout and stderr streams of the subordinate process, add `.stream()`
111call to the built-up `Execs`:
005bd4b4
AK
112
113```rust
114// Before
c083880c 115p.cargo("run").run();
005bd4b4
AK
116
117// After
c083880c 118p.cargo("run").stream().run();
506786d0
AK
119```
120
6049121b 121Alternatively to build and run a custom version of cargo simply run `cargo build`
2461571e 122and execute `target/debug/cargo`. Note that `+nightly`/`+stable` (and variants),
c2cd0fde 123being [rustup] features, won't work when executing the locally
4a9066ab
DW
124built cargo binary directly, you have to instead build with `cargo +nightly build`
125and run with `rustup run` (e.g `rustup run nightly
126<path-to-cargo>/target/debug/cargo <args>..`) (or set the `RUSTC` env var to point
127to nightly rustc).
6049121b 128
c2cd0fde
HY
129[rustup]: https://rustup.rs/
130
131
506786d0
AK
132## Logging
133
c2cd0fde 134Cargo uses [`env_logger`], so you can set
782266aa 135`CARGO_LOG` environment variable to get the logs. This is useful both for diagnosing
f7c91ba6
AR
136bugs in stable Cargo and for local development. Cargo also has internal hierarchical
137profiling infrastructure, which is activated via `CARGO_PROFILE` variable
506786d0
AK
138
139```
f7c91ba6 140# Outputs all logs with levels debug and higher
782266aa 141$ CARGO_LOG=debug cargo generate-lockfile
506786d0 142
f7c91ba6 143# Don't forget that you can filter by module as well
782266aa 144$ CARGO_LOG=cargo::core::resolver=trace cargo generate-lockfile
005bd4b4 145
506786d0
AK
146# Output first three levels of profiling info
147$ CARGO_PROFILE=3 cargo generate-lockfile
005bd4b4 148```
c2cd0fde
HY
149
150[`env_logger`]: https://docs.rs/env_logger/*/env_logger/