Depedency Management

1. Welcome and Icebreaker:

Welcome back!

If you could instantly add any pre-built “dependency” (like a skill, a tool, or a resource) to your life, what would it be and why?

2. Outline the Session:

Here’s the plan:

  1. Concept Explanation: We’ll discuss what dependencies are, why they’re important, and how Cargo helps manage them. We’ll cover key concepts like Cargo.toml, Cargo.lock, crates.io, semantic versioning, and adding, updating, and removing dependencies.
  2. Live Coding Demonstration: We’ll create a new project, add a dependency, use it in our code, and observe how Cargo handles the process. We’ll also demonstrate updating and removing dependencies.
  3. Tasks: You’ll get exercises to practice managing dependencies in your own projects.

Learning Outcomes: By the end of this session, you will be able to:

  • Understand the concept of dependencies in software development.
  • Use Cargo.toml to declare project dependencies.
  • Understand the role of Cargo.lock.
  • Add dependencies to a project using cargo add.
  • Use dependencies in your code.
  • Update dependencies using cargo update.
  • Remove dependencies using cargo remove.
  • Understand the basics of semantic versioning (SemVer).
  • Find and explore crates on crates.io.

Expectations: Dependency management is a core part of modern software development. Pay close attention to how Cargo simplifies this process for Rust projects.

3. Concept Explanation:

  • Dependencies: Dependencies are external libraries (crates) that your project relies on. They provide pre-built functionality that you can use in your code.
  • Why Use Dependencies?
    • Code Reusability: Avoid reinventing the wheel.
    • Faster Development: Leverage existing solutions.
    • Community Contributions: Benefit from the work of other developers.
  • Cargo’s Role: Cargo is Rust’s build system and package manager. It handles:
    • Downloading and building dependencies.
    • Managing dependency versions.
    • Building your project.
    • Running tests.
    • Publishing your own crates.
  • Cargo.toml: This file is the manifest for your project. It contains:
    • Project metadata (name, version, authors).
    • Dependencies: A list of the external crates your project depends on, along with their version requirements.
    • Other configuration settings.
  • Cargo.lock: This file is automatically generated by Cargo. It locks the specific versions of all your dependencies (including transitive dependencies – dependencies of your dependencies) to ensure reproducible builds. You should not edit this file manually. It should be committed to version control.
  • **crates.io:** This is the official Rust package registry (like npm for JavaScript or PyPI for Python). It’s where Cargo downloads crates from.
  • Semantic Versioning (SemVer): A versioning scheme (MAJOR.MINOR.PATCH) that helps manage compatibility:
    • MAJOR: Incompatible API changes.
    • MINOR: New features, but backwards-compatible.
    • PATCH: Bug fixes, backwards-compatible.
    • Cargo uses version specifiers (e.g., ^, ~, ) to control which versions of a dependency are acceptable.
      • ^1.2.3: Compatible with version 1.x.x, where x >= 2 and 3 (allows minor and patch updates). This is the default.
      • ~1.2.3: Compatible with version 1.2.x, where x >= 3 (allows only patch updates).
      • : Any version (generally not recommended).
      • 1.2.3: Exactly version.
  • Adding Dependencies:
    • cargo add (recommended): cargo add <crate_name> automatically adds the dependency to Cargo.toml and downloads it.
    • Manually: You can edit Cargo.toml directly, but cargo add is usually easier.
  • Updating Dependencies:
    • cargo update: Updates dependencies to the latest compatible versions (according to the version specifiers in Cargo.toml). It also updates Cargo.lock.
  • Removing Dependencies:
    • cargo remove (recommended): cargo remove <crate_name> removes the dependency from Cargo.toml and updates the project.
    • Manually: You can edit Cargo.toml directly.

4. Live Coding Demonstration:

Let’s create a new project and add the rand crate, which provides random number generation:

cargo new my_project
cd my_project

Open project in your IDE

1. Add a Dependency:

cargo add rand

This command does two things:

  • Updates Cargo.toml: It adds a line like rand = "0.8" (or whatever the latest version is) to the [dependencies] section.
  • Downloads the Crate: It downloads the rand crate and its dependencies.

Cargo.toml (after cargo add rand):

[package]
name = "my_project"
version = "0.1.0"
edition = "2021"

[dependencies]
rand = "0.8" # The rand crate was added here

2. Use the Dependency:

Modify src/main.rs:

// src/main.rs

use rand::Rng; // Import the Rng trait from the rand crate

fn main() {
    let mut rng = rand::thread_rng(); // Get a random number generator
    let random_number = rng.gen_range(1..=100); // Generate a number between 1 and 100 (inclusive)
    println!("Random number: {}", random_number);
}

3. Run the Project:

cargo run

Cargo will build the project (including the rand crate) and run it. You’ll see a random number printed to the console.

4. Update Dependencies (Optional):

cargo update

This command updates all dependencies to their latest compatible versions and updates Cargo.lock.

5. Remove a Dependency (Optional):

cargo remove rand

This command removes rand from Cargo.toml and updates Cargo.lock. You’ll also need to remove the use rand::Rng; line and the code that uses rand from src/main.rs to avoid compilation errors.

6. Exploring crates.io: Open https://crates.io/ and find and analyze rand crate.

5. Tasks

  1. Add ferris-says: Create a new project. Add the ferris-says crate as a dependency. Use it to make Ferris (the Rust mascot) say something in your terminal. (You can find examples in the ferris-says documentation on crates.io).
  2. Cargo.toml Exploration: Examine the Cargo.toml file after adding a dependency. Understand the different sections and the meaning of the version specifier.
  3. Cargo.lock Examination: Look at the Cargo.lock file. Notice how it lists the exact versions of all dependencies. Don’t modify this file manually!
  4. Update and Observe: Add a dependency, run your project, then run cargo update. Check Cargo.lock before and after the update to see how the versions might have changed.
  5. Multiple Dependencies: Add two or three different dependencies to a project (e.g., rand, reqwest for making HTTP requests, serde for serialization/deserialization). Use them in your code.
  6. Find a Crate: Go to crates.io and find a crate that interests you. Read its documentation. Add it to a new project and try using it.
  7. Version Specifiers: Experiment with different version specifiers in Cargo.toml (e.g., ^, ~, , a specific version number). Use cargo update to see how the chosen version changes based on the specifier. Important: Be careful with (any version) – it’s generally not recommended for production code, as it can lead to unexpected breakage if a dependency makes a breaking change.