% Frequently Asked Questions
No. The plan for Cargo is to use crates.io, like npm or Rubygems do with npmjs.org and rubygems.org.
We plan to support git repositories as a source of packages forever, because they can be used for early development and temporary patches, even when people use the registry as the primary source of packages.
We think that it’s very important to support multiple ways to download packages, including downloading from GitHub and copying packages into your project itself.
That said, we think that crates.io offers a number of important benefits, and will likely become the primary way that people download packages in Cargo.
For precedent, both Node.js’s npm and Ruby’s bundler support both a central registry model as well as a Git-based model, and most packages are downloaded through the registry in those ecosystems, with an important minority of packages making use of git-based packages.
Some of the advantages that make a central registry popular in other languages include:
Yes!
Cargo handles compiling Rust code, but we know that many Rust projects link against C code. We also know that there are decades of tooling built up around compiling languages other than Rust.
Our solution: Cargo allows a package to specify a script (written in Rust) to run before invoking rustc
. Rust is leveraged to implement platform-specific configuration and refactor out common build functionality among packages.
make
(or ninja
, or ...)Indeed. While we intend Cargo to be useful as a standalone way to compile Rust projects at the top-level, we know that some people will want to invoke Cargo from other build tools.
We have designed Cargo to work well in those contexts, paying attention to things like error codes and machine-readable output modes. We still have some work to do on those fronts, but using Cargo in the context of conventional scripts is something we designed for from the beginning and will continue to prioritize.
Rust itself provides facilities for configuring sections of code based on the platform. Cargo also supports platform-specific dependencies, and we plan to support more per-platform configuration in Cargo.toml
in the future.
In the longer-term, we’re looking at ways to conveniently cross-compile projects using Cargo.
production
or test
?We support environments through the use of profiles to support:
-g --opt-level=0
for development and --opt-level=3
for production).hamcrest
for test assertions).#[cfg]
cargo test
commandYes!
All commits to Cargo are required to pass the local test suite on Windows. If, however, you find a Windows issue, we consider it a bug, so please file an issue.
Cargo.lock
in version control, but not libraries?The purpose of a Cargo.lock
is to describe the state of the world at the time of a successful build. It is then used to provide deterministic builds across whatever machine is building the project by ensuring that the exact same dependencies are being compiled.
This property is most desirable from applications and projects which are at the very end of the dependency chain (binaries). As a result, it is recommended that all binaries check in their Cargo.lock
.
For libraries the situation is somewhat different. A library is not only used by the library developers, but also any downstream consumers of the library. Users dependent on the library will not inspect the library’s Cargo.lock
(even if it exists). This is precisely because a library should not be deterministically recompiled for all users of the library.
If a library ends up being used transitively by several dependencies, it’s likely that just a single copy of the library is desired (based on semver compatibility). If all libraries were to check in their Cargo.lock
, then multiple copies of the library would be used, and perhaps even a version conflict.
In other words, libraries specify semver requirements for their dependencies but cannot see the full picture. Only end products like binaries have a full picture to decide what versions of dependencies should be used.
*
as a version for their dependencies?As of January 22nd, 2016, crates.io rejects all packages (not just libraries) with wildcard dependency constraints.
While libraries can, strictly speaking, they should not. A version requirement of *
says “This will work with every version ever,” which is never going to be true. Libraries should always specify the range that they do work with, even if it’s something as general as “every 1.x.y version.”
Cargo.toml
?As one of the most frequent interactions with Cargo, the question of why the configuration file is named Cargo.toml
arises from time to time. The leading capital-C
was chosen to ensure that the manifest was grouped with other similar configuration files in directory listings. Sorting files often puts capital letters before lowercase letters, ensuring files like Makefile
and Cargo.toml
are placed together. The trailing .toml
was chosen to emphasize the fact that the file is in the TOML configuration format.
Cargo does not allow other names such as cargo.toml
or Cargofile
to emphasize the ease of how a Cargo repository can be identified. An option of many possible names has historically led to confusion where one case was handled but others were accidentally forgotten.
Cargo is often used in situations with limited or no network access such as airplanes, CI environments, or embedded in large production deployments. Users are often surprised when Cargo attempts to fetch resources from the network, and hence the request for Cargo to work offline comes up frequently.
Cargo, at its heart, will not attempt to access the network unless told to do so. That is, if no crates comes from crates.io, a git repository, or some other network location, Cargo will never attempt to make a network connection. As a result, if Cargo attempts to touch the network, then it's because it needs to fetch a required resource.
Cargo is also quite aggressive about caching information to minimize the amount of network activity. It will guarantee, for example, that if cargo build
(or an equivalent) is run to completion then the next cargo build
is guaranteed to not touch the network so long as Cargo.toml
has not been modified in the meantime. This avoidance of the network boils down to a Cargo.lock
existing and a populated cache of the crates reflected in the lock file. If either of these components are missing, then they're required for the build to succeed and must be fetched remotely.
As of Rust 1.11.0 Cargo understands a new flag, --frozen
, which is an assertion that it shouldn‘t touch the network. When passed, Cargo will immediately return an error if it would otherwise attempt a network request. The error should include contextual information about why the network request is being made in the first place to help debug as well. Note that this flag does not change the behavior of Cargo, it simply asserts that Cargo shouldn’t touch the network as a previous command has been run to ensure that network activity shouldn't be necessary.
For more information about vendoring, see documentation on source replacement.