How to Run Specific Examples in a Cargo Project

Use the `cargo run --example <name>` command to execute a specific example file located in your project's `examples` directory.

When one binary isn't enough

You are building a library for parsing configuration files. The library exposes a clean API, but the documentation needs to show three distinct workflows: parsing a simple TOML file, handling merge conflicts, and streaming large JSON inputs. Your src/main.rs only contains a placeholder that prints "Hello". You write three separate files to demonstrate each workflow. Now you need to run just the streaming example to verify the logic, without rebuilding the entire project or editing the main binary.

This is the daily reality of library authors and API designers. Rust solves this with examples. Examples let you attach multiple standalone scripts to a single crate. Each script can exercise the library code, demonstrate usage patterns, or test edge cases. Cargo treats these scripts as first-class targets, compiling and running them on demand.

How Cargo handles examples

Cargo scans the examples/ directory at the root of your crate. Every .rs file in that directory becomes a separate binary target. The filename determines the target name. A file named examples/stream.rs creates a target called stream.

When you run cargo run --example stream, Cargo compiles that specific file as a binary. It links the binary against your library crate if one exists. The result is an executable that runs in isolation. You can have as many examples as you need. They do not interfere with your main binary or your library code.

Examples are not just scripts. They are integration points. Because they link to your library, they verify that your public API works as expected. If an example fails to compile, your library's public interface has a problem. If an example crashes at runtime, your library has a bug. This makes examples a powerful tool for maintaining quality.

Convention aside: developers often use use crate:: inside example files to import from the library. This refers to the library target of the current package, not the example file itself. It keeps the code portable if you rename the crate later. Avoid hardcoding the crate name with use my_crate:: unless you have a specific reason.

Minimal working example

Start with a simple library that adds two numbers. The library lives in src/lib.rs. The example lives in examples/demo.rs.

// src/lib.rs
/// Add two integers and return the result.
/// This function is the core logic of the library.
pub fn add(a: i32, b: i32) -> i32 {
    a + b
}
// examples/demo.rs
/// Demonstrate how to use the add function from the library.
/// This file acts as a standalone binary for testing.
use crate::add;

fn main() {
    // Call the library function with hardcoded values.
    let result = add(2, 2);
    
    // Print the result to verify correctness.
    println!("Result: {}", result);
}

Run the example with the --example flag. Cargo finds examples/demo.rs, compiles it, links the library, and executes the binary.

cargo run --example demo

The output shows the result. Cargo handles the build process automatically. You do not need to specify the file extension or the directory path. The target name matches the filename without the .rs extension.

Treat examples as living documentation. If the example breaks, your docs are lying.

Passing arguments to your example

Examples often need input. You might want to pass a filename, a flag, or a configuration value. Cargo separates its own flags from the program's arguments using the double-dash -- separator.

Update the example to read command-line arguments.

// examples/cli_demo.rs
/// Parse command-line arguments and display them.
/// This shows how to receive input from the user.
fn main() {
    // Skip the program name and collect remaining args.
    let args: Vec<String> = std::env::args().skip(1).collect();
    
    // Check if any arguments were provided.
    if args.is_empty() {
        println!("No arguments provided.");
        return;
    }
    
    // Print the arguments for verification.
    println!("Received args: {:?}", args);
}

Run the example with arguments after the separator.

cargo run --example cli_demo -- --verbose --count 5

The -- tells Cargo to stop parsing flags. Everything after -- goes directly to the binary. Without the separator, Cargo tries to interpret --verbose as its own flag and fails.

The -- separator is your shield against Cargo eating your arguments. Always include it when passing data to the program.

Realistic workflow: features and release mode

Examples often depend on optional functionality. Your library might have a feature flag for async support or JSON output. You can enable features when running an example using the --features flag.

cargo run --example advanced_query --features "async-support"

Cargo compiles the library with the specified feature enabled. The example gains access to the additional functionality. This lets you test feature-gated code without modifying the default configuration.

Performance testing requires release mode. Debug builds include checks and lack optimizations. Run an example in release mode by adding --release before the example flag.

cargo run --release --example benchmark

Cargo builds the example and the library with optimizations enabled. The binary runs faster. Use this for timing measurements or load testing.

Workspaces add another layer. If your project contains multiple crates, you must specify which package contains the example. Use the -p flag to target a specific package.

cargo run -p my-crate --example specific_example

Cargo looks for the example inside my-crate. This prevents ambiguity when multiple packages define examples with the same name.

Examples are for exploration. Binaries are for production. Keep them separate.

Pitfalls and compiler errors

Naming collisions cause confusion. If you have src/bin/demo.rs and examples/demo.rs, both create targets named demo. Running cargo run fails because Cargo cannot decide which binary to execute. You must disambiguate.

Use cargo run --bin demo for the production binary. Use cargo run --example demo for the example. Cargo rejects ambiguous commands with an error.

error: a bin target must be available for `cargo run`

This error appears when no default binary exists and you run cargo run without flags. Cargo needs to know what to run. Specify a target explicitly.

Argument parsing errors happen when you forget the separator. Cargo tries to parse your program's arguments as its own flags.

error: unexpected argument '--verbose' found

The compiler rejects the command. Add -- before your arguments. This error is common when switching between running binaries and running examples.

Module imports can trip you up. Examples are separate compilation units. You cannot access private items from the library. Only public items are visible. If you try to use a private function, the compiler rejects it.

error[E0603]: function `helper` is private

This error indicates you are trying to access internal implementation details. Examples should only test the public API. If you need to test private logic, use unit tests inside the library code.

Workspace examples require the package flag. Running an example without -p in a workspace fails if the example name is not unique across all packages.

error: could not find `examples` directory

Or Cargo might pick the wrong package. Always use -p in workspaces to be explicit.

Trust the borrow checker. It usually has a point. If an example fails to compile, fix the code. Do not ignore errors.

Decision matrix

Choose the right tool for the job. Examples, binaries, and tests serve different purposes. Use the parallel structure below to decide.

Use cargo run --example name when you want to execute a standalone script that demonstrates library usage or tests a specific workflow without shipping it. Use cargo run --bin name when you are running a production binary that ships with your crate. Use cargo test --example name when you want to run unit tests inside an example file to verify the demonstration logic. Use cargo run --example name --features flag when your example depends on optional functionality that isn't enabled by default. Use cargo run --release --example name when you need performance measurements or optimized execution for benchmarking. Use cargo run -p package --example name when you are working in a workspace and need to target a specific crate.

Examples are your library's playground. Keep them clean and focused.

Where to go next