You can think of crate as the code that is compiled and package as the Rust project, which also includes the dependencies.
Cargo is actually a package that contains the binary crate for the command-line tool you’ve been using to build your code.
The Cargo package also contains a library crate that the binary crate depends on. Other projects can depend on the Cargo library crate to use the same logic the Cargo command-line tool uses.
A crate root is the first file that the compiler looks for, all the other files are compiled because the crate root imports them.
Cargo follows a convention that src/main.rs is the crate root of a binary crate with the same name as the package. Likewise, Cargo knows that if the package directory contains src/lib.rs, the package contains a library crate with the same name as the package, and src/lib.rs is its crate root.
Modules are a group of files that define some functions, struct, enums, etc. You may know them as namespaces. Modules are useful to organize your code.
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:
mod garden {}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 permit it) using the path to the module. For example, an Asparagus type in the garden vegetables module would be found at crate::garden::vegetables::Asparagus
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.
use keywordWithin 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.
Suppose we have a project like this:
backyard
├── Cargo.lock
├── Cargo.toml
└── src
├── garden
│ └── vegetables.rs
├── garden.rs
└── main.rs
In src/main.rs
use crate::garden::vegetables::Asparagus;
pub mod garden;
fn main() {
let plant = Asparagus {};
println!("I'm growing {:?}!", plant);
}
In src/garden.rs
pub mod vegetables;
In src/garden/vegetables.rs
#[derive(Debug)]
pub struct Asparagus {}
We have three keyword for defining module paths:
crate which refers to the root of the project, from src/super, the parent module, like ../ for filesystemsself, the current module, like ./ for filesystemsYou can alias names with as, useful in case of name collision.
use std::io::Result as IoResult;
You can group nested paths.
use std::cmp::Ordering;
use std::io;
use std::{cmp::Ordering, io};
You can import everything from a module with '*'.
use std::collections::*;
A common Rust pattern for libraries is to have all the most common stuff to import in the prelude module.
use bevy::prelude::*;