Packages and Crates in Rust
In this lesson, you will learn about packages and crates in Rust. These concepts form the foundation of how Rust projects are organized, built, and shared.
Understanding packages and crates is essential before working with real-world Rust applications.
What Is a Crate?
A crate is the smallest unit of compilation in Rust. It can contain functions, structs, enums, modules, and other Rust code.
There are two main types of crates:
- Binary crates – executable programs
- Library crates – reusable code without a main function
Binary Crates
A binary crate produces an executable file.
It must contain a main function.
fn main() {
println!("Hello from a binary crate!");
}
Every Rust application you run is a binary crate.
Library Crates
A library crate is used to share code between projects.
It does not have a main function.
Library crates usually expose functionality using public functions.
pub fn greet() {
println!("Hello from a library crate!");
}
What Is a Package?
A package is a bundle that contains one or more crates along with configuration files.
A package is defined by a file called Cargo.toml.
A Rust package can contain:
- Zero or one library crate
- One or more binary crates
Cargo.toml File
The Cargo.toml file contains metadata and dependencies for a package.
[package]
name = "my_project"
version = "0.1.0"
edition = "2021"
[dependencies]
Cargo uses this file to build, run, and manage the project.
Default Package Structure
When you create a project using Cargo, Rust follows a standard structure.
my_project/
├── Cargo.toml
└── src/
├── main.rs
└── lib.rs
Here:
main.rs→ binary cratelib.rs→ library crate
Using a Library Crate in a Binary
A binary crate can use functions from its library crate.
// lib.rs
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
// main.rs
use my_project::add;
fn main() {
println!("{}", add(2, 3));
}
External Crates
Rust allows you to use external crates published on crates.io.
To use an external crate, add it to Cargo.toml.
[dependencies]
rand = "0.8"
Then import it using use.
use rand::Rng;
fn main() {
let num = rand::thread_rng().gen_range(1..=10);
println!("{}", num);
}
Why Packages and Crates Matter
Packages and crates allow Rust developers to:
- Organize large applications
- Reuse code efficiently
- Share libraries with the community
- Build scalable systems
📝 Practice Exercises
Exercise 1
Create a binary crate with a main function.
Exercise 2
Create a library crate with a public function.
Exercise 3
Call a library function from a binary crate.
Exercise 4
Add an external crate using Cargo.toml.
✅ Practice Answers
Answer 1
fn main() {
println!("Binary crate");
}
Answer 2
pub fn hello() {
println!("Hello");
}
Answer 3
use my_project::hello;
fn main() {
hello();
}
Answer 4
[dependencies]
serde = "1.0"
What’s Next?
In the next lesson, you will learn about Cargo (Advanced) — workspace management, build profiles, and advanced dependency handling.