Skip to content

Packaging, Crates, and Modules

Crates

A crate is the smallest piece of code. It can be either a library or a binary.

Binaries are programs that compile into an executable, and must have a main function. The entrypoint to a binary is src/main.rs within the package.

Libraries are meant to be imported and used by other projects. The entrypoint to a library is src/lib.rs and the compiler will create a library with the same name as the package.

Packages

A package is one or more crates that do something. It contains a cargo.yaml file that describes how to build the package. A package can have multiple binary crates, but only one library crate.

Modules

Modules provide a way to break code into different files and use their paths to import/export functionality.

Cheat Sheet from the Rust Book

  • Start from the crate root: When compiling a crate, the compiler first looks in the crate root file (usually src/lib.rs for a library crate or src/main.rs for a binary crate) for code to compile.
  • Declaring modules: In the crate root file, you can declare new modules; say, you declare a “garden” module with mod garden;. The compiler will look for the module’s code in these places:
    • Inline, within curly brackets that replace the semicolon following mod garden
    • In the file src/garden.rs
    • In the file src/garden/mod.rs
  • Declaring submodules: In any file other than the crate root, you can declare submodules. For example, you might declare mod vegetables; in src/garden.rs. The compiler will look for the submodule’s code within the directory named for the parent module in these places:
    • Inline, directly following mod vegetables, within curly brackets instead of the semicolon
    • In the file src/garden/vegetables.rs
    • In the file src/garden/vegetables/mod.rs
  • Paths to code in modules: Once a module is part of your crate, you can refer to code in that module from anywhere else in that same crate, as long as the privacy rules allow, using the path to the code. For example, an Asparagus type in the garden vegetables module would be found at crate::garden::vegetables::Asparagus.
  • Private vs public: Code within a module is private from its parent modules by default. To make a module public, declare it with pub mod instead of mod. To make items within a public module public as well, use pub before their declarations.
  • The use keyword: Within a scope, the use keyword creates shortcuts to items to reduce repetition of long paths. In any scope that can refer to crate::garden::vegetables::Asparagus, you can create a shortcut with use crate::garden::vegetables::Asparagus; and from then on you only need to write Asparagus to make use of that type in the scope.

Making things public

By default, everything you declare in rust is private. To make them public and usable by other files, use the pub keyword.

rust
pub struct Breakfast {
    pub toast: String,
    seasonal_fruit: String,
}

impl Breakfast {
    pub fn summer(toast: &str) -> Breakfast {
        Breakfast {
            toast: String::from(toast),
            seasonal_fruit: String::from("peaches"),
        }
    }
}

pub enum Appetizer {
    Soup,
    Salad,
}

For libraries, or any other module, you can re-export a module with pub use. Then you can import it from that re-exporting module's scope if it is deeply nested.

Additional shorthands

rust
use std::cmp::Ordering;
use std::io;
// Becomes...
use std::{cmp::Ordering, io};

use std::io;
use std::io::Write;
// Becomes...
use std::io::{self, Write};

// Brings everything from that module into scope
use std::collections::*;
// Use with caution, because it becomes difficult to determine what is in scope