Rust Development Environment

The src Directory

In a Cargo package, the src/ directory holds all Rust source files (.rs) that make up the package's library and binary crates. Cargo uses a set of conventional file paths inside src/ to automatically discover compilation targets without requiring you to list every source file in Cargo.toml.

Standard src/ Directory Layout

A full-featured Cargo package can contain a library root, a default binary root, additional binaries, and module subdirectories inside src/:

my_package/
├── Cargo.toml
└── src/
    ├── lib.rs              <-- Library crate root (at most 1 per package)
    ├── main.rs             <-- Default binary crate root (compiled to `target/debug/my_package`)
    ├── config.rs           <-- Module file (`mod config;` declared in `lib.rs` or `main.rs`)
    ├── network/            <-- Submodule directory (`mod network;`)
    │   ├── mod.rs          <-- (Or `src/network.rs` alongside `src/network/`)
    │   └── client.rs       <-- Submodule `network::client` (`mod client;`)
    └── bin/                <-- Additional binary executables (`cargo run --bin <name>`)
        ├── migrate.rs      <-- Single-file binary target (`migrate`)
        └── server/         <-- Multi-file binary target (`server`)
            ├── main.rs
            └── routes.rs

Conventional Targets Discovered in src/

Cargo inspects src/ and automatically registers the following compilation targets:

File Path in src/ Target Type Resulting Crate / Binary Name How to Run or Build
src/lib.rs Library crate (--lib) Package name (with - replaced by _) cargo build --lib / cargo test --lib
src/main.rs Default binary crate (--bin) Package name cargo run (or cargo run --bin <pkg_name>)
src/bin/<name>.rs Additional single-file binary <name> cargo run --bin <name>
src/bin/<name>/main.rs Additional multi-file binary <name> cargo run --bin <name>

How rustc Discovers Other Files in src/

Unlike Go or Java—which automatically compile every source file placed in a directory—rustc starts ONLY at the crate root file (src/main.rs or src/lib.rs) and compiles other .rs files in src/ only if they are explicitly declared with mod <name>; in the module tree!

If you create src/helper.rs but never write mod helper; inside src/main.rs (or src/lib.rs), src/helper.rs is completely ignored during compilation.

src/main.rs (Crate Root)
   |
   +-- `mod config;`   ---> Compiler loads and compiles `src/config.rs`
   |
   +-- `mod network;`  ---> Compiler loads and compiles `src/network.rs` (or `src/network/mod.rs`)
          |
          +-- `pub mod client;` ---> Compiler loads `src/network/client.rs`

Example: Connecting a Module File in src/

Suppose your src/ directory contains two files: src/main.rs and src/math.rs.

src/math.rs:

pub fn double(n: i32) -> i32 {
    n * 2
}

src/main.rs:

mod math; // Tells `rustc` to load `src/math.rs` as the `math` module

fn main() {
    println!("21 doubled is {}", math::double(21));
}
21 doubled is 42

Modern Module Subdirectories (src/network.rs vs src/network/mod.rs)

When a module like network has its own child submodules (network::client), Rust supports two directory layouts inside src/:

Style Parent Module File Child Module File (network::client) Status
Modern (2018+ Edition) src/network.rs src/network/client.rs Recommended (avoids having dozens of tabs all named mod.rs in your editor)
Older (2015 Edition) src/network/mod.rs src/network/client.rs Supported, but do not create both src/network.rs and src/network/mod.rs at the same time (E0761)

Multiple Binaries in src/bin/

When a project needs helper CLI utilities alongside its main application (such as a database migration tool migrate or a data seeding script seed), place each utility inside src/bin/:

// src/bin/seed.rs
fn main() {
    println!("Seeding database with initial records...");
}

Run a specific binary in src/bin/ using --bin:

cargo run --bin seed
   Compiling my_package v0.1.0 (/Users/username/my_package)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.19s
     Running `target/debug/seed`
Seeding database with initial records...

When both src/main.rs and src/bin/*.rs exist in the same package, running bare cargo run without --bin becomes ambiguous unless you set default-run in Cargo.toml:

[package]
name = "my_package"
version = "0.1.0"
edition = "2024"
default-run = "my_package"

Directories Outside src/ Recognized by Cargo

While application and library production code lives inside src/, Cargo also recognizes three sibling directories at the package root for tests, examples, and benchmarks:

Sibling Directory Purpose Invoked Via
tests/*.rs Integration tests (each file is compiled as a separate crate testing your library's public API) cargo test
examples/*.rs Standalone runnable example programs demonstrating how to use your library cargo run --example <name>
benches/*.rs Performance benchmarks cargo bench