17.2 Crates: The Building Blocks of Rust Projects
Crates are the fundamental units of code compilation and distribution in Rust.
17.2.1 What Is a Crate?
A crate is the smallest unit of code that the Rust compiler considers at a time. It is either a binary or a library and forms a module tree starting from a crate root.
17.2.2 Binary and Library Crates
- Binary Crates: Generate executables and must have a
main
function. They are the entry points for programs. - Library Crates: Provide reusable functionality and do not have a
main
function. They produce.rlib
files and can be included as dependencies.
Example:
- Binary Crate:
src/main.rs
- Library Crate:
src/lib.rs
17.2.3 The Crate Root
The crate root is the starting point of compilation for any Rust crate. It is the source file that defines the module hierarchy and links to the rest of the code in the crate.
For binary crates, the crate root is typically src/main.rs
, serving as the entry point of the executable program.
For library crates, the crate root is src/lib.rs
, providing the public API for the library.
The crate root establishes an implicit (or virtual) root module named crate
, into which the entire source code of the crate is embedded. This virtual module serves as a global namespace for the crate. To reference items at the top level of the crate from within submodules, the crate::
prefix can be used.
17.2.4 External Crates
External crates allow you to integrate third-party libraries into your Rust project. These crates are managed by Cargo and are typically hosted on crates.io.
Declaring Crates in Cargo.toml
Add dependencies in the [dependencies]
section:
[dependencies]
rand = "0.8" # Version 0.8 of the rand crate
serde = { version = "1.0", features = ["derive"] } # With features
Using External Crates in Code
After declaring the dependency, you can bring external crates into scope using the use
keyword:
use rand::Rng; fn main() { let mut rng = rand::thread_rng(); let n: u32 = rng.gen_range(1..101); println!("Generated number: {}", n); }
Note that the standard library std
is also a crate that's external to our package. Because the standard library is shipped with the Rust compiler, we don't have to list std
in Cargo.toml
. But we do need to refer to it with use
to bring items from there into our package's scope. For example, with HashMap
we would use this line:
#![allow(unused)] fn main() { use std::collections::HashMap; }
17.2.5 The extern crate
Keyword (Legacy)
In earlier versions of Rust, the extern crate
keyword was required to bring external crates into scope, as in extern crate rand;
. As of the 2018 edition, this is no longer necessary for most cases, and you can use external crates directly with use
.