What is the exact difference between a Crate and a Package?

I come from a Java background and have recently started with Rust.

The official Rust doc is pretty self-explanatory except the chapter that explains Crates and Packages.

The official doc complicates it with so many ORs and ANDs while explaining the two.

This reddit post explains it a little better, but is not thorough.

What is the exact difference between a Crate and Package in Rust? Where/When do we use them?

Much thanks!

Upvotes: 11

Views: 2802

Answers (2)

poolie
poolie

Reputation: 9515

The Rust book section on packages and crates is pretty clear, but to make this very concrete:

A package is a directory containing a Cargo.toml and typically with a src/ and tests/ directory, and excluding any child directories that are themselves packages. (There are some edge cases and variations, including a "virtual workspace root" that has a Cargo.toml but that only acts as a container for packages in subdirectories.)

A crate corresponds to a single target declared in the Cargo.toml: typically either a binary or a library.

The most common case is that the package and crate are one-to-one: the package defines only a single target, either a library or a binary.

Probably the second most common case is a package with two crates, for a binary (with main in say src/main.rs) and a library used by that binary (from src/lib.rs).

Upvotes: 1

Elias Holzmann
Elias Holzmann

Reputation: 3669

Crates

From the perspective of the Rust compiler, "crate" is the name of the compilation unit. A crate consists of an hierarchy of modules in one or multiple files. This is in contrast to most "traditional" compiled languages like Java, C or C++, where the compilation unit is a single file.

From the perspective of an user, this definition isn't really helpful. Indeed, in most cases, you will need to distinguish between two types of crates:

  • binary crates can be compiled to executables by the Rust compiler. For example, Cargo, the Rust package manager, is a binary crate translated by the Rust compiler to the executable that you use to manage your project.
  • library crates are what you'd simply call libraries in other languages. A binary crate can depend on library crates to use functionality supplied by the libraries.

Packages

The concept of packages does not originate in the Rust compiler, but in Cargo, the Rust package manager. At least for simple projects, a package is also what you will check into version control.

A package consists of one or multiple crates, but no more than one library crate.

Creating packages

  • to create a new package consisting of one binary crate, you can run cargo new
  • to create a new package consisting of one library crate, you can run cargo new --lib
  • to create a package consisting of a library as well as one or multiple binaries, you can run either cargo new or cargo new --lib and then modify the package directory structure to add the other crate

When should you use crates, and when should you use packages?

As you can see now, this question doesn't really make sense – you should and must always use both. A package can't exist without at least one crate, and a crate is (at least if you are using Cargo) always part of a package.

Therefore, a better question is this:

When should you put multiple crates into one package?

There are multiple reasons to have more than one crate in a package. For example:

  • If you have a binary crate, it is idiomatic to have the "business logic" in a library in the same package. This has multiple advantages:
  • If you have a library crate that generates some files (a database engine or something like that), you may want to have a helper binary to inspect those files

Note that if you have a very big project, you may instead want to use the workspace feature of Cargo in these cases.

Upvotes: 16

Related Questions