| Contents |

4 Rustc and Cargo

This chapter introduces the Rust compiler, rustc, and the essential build system and package manager, Cargo. In C or C++, managing the build process (e.g., with Make or CMake) and handling external libraries are typically separate tasks using different tools. Rust, however, integrates both functions tightly within Cargo. Much of Rust’s standard library is deliberately minimal, relying on external libraries—called crates in Rust—for common functionality like random number generation or regular expressions. We will explore how Cargo simplifies adding dependencies, compiling code, managing projects, and integrating helpful development tools. This overview provides the necessary foundation; Chapter 23 offers a more comprehensive look at Cargo’s capabilities.


4.1 Compiling Rust Code: rustc

The core tool for turning Rust source code into executable programs or libraries is the Rust compiler, rustc. For a very simple project contained in a single file, you can invoke it directly:

rustc main.rs

This command compiles main.rs and produces an executable file (named main on Linux/macOS, main.exe on Windows) in the current directory.

While functional, manually invoking rustc quickly becomes impractical for projects involving multiple source files, external libraries (dependencies), or different build configurations (like debug vs. release builds). This mirrors the complexity of managing non-trivial C/C++ projects with direct compiler calls, which led to the development of tools like Make and CMake. In Rust, the standard solution is Cargo.

4.2 The Build System and Package Manager: Cargo

Cargo is Rust’s official build system and package manager, designed to handle the complexities of building Rust projects. It orchestrates the compilation process (using rustc behind the scenes), fetches and manages dependencies, runs tests, generates documentation, and much more. For most Rust development, you will interact primarily with Cargo rather than calling rustc directly.

Key tasks simplified by Cargo include:

4.2.1 Creating a New Cargo Project

Starting a new project is straightforward. Use the cargo new command:

# Create a new binary (executable) project
cargo new my_executable_project

# Create a new library (crate) project
cargo new --lib my_library_project

This creates a directory named my_executable_project (or my_library_project) with a standard structure:

my_executable_project/
├── .gitignore         # Standard git ignore file for Rust projects
├── Cargo.toml         # Project manifest file (configuration, dependencies)
└── src/
    └── main.rs        # Main source file (for binaries)
                       # or lib.rs (for libraries)

4.2.2 Building, Checking, Running, and Testing with Cargo

Once your project structure is in place, you can manage the build, test, and run cycle using these core Cargo commands:

First, compile your project:

cargo build

This command compiles your project using the default debug profile. Debug builds prioritize faster compilation and include helpful additions for development, such as debugging information and runtime checks (like integer overflow detection). The resulting binary is placed in the target/debug/ directory.

For an optimized build intended for final testing or distribution, use the --release flag:

cargo build --release

This uses the release profile, which enables significant compiler optimizations for better runtime performance, though compilation takes longer. The output is placed in target/release/.

To quickly check your code for errors without the overhead of generating the final executable:

cargo check

This command runs the compiler’s analysis passes but stops before code generation, making it significantly faster than cargo build. It’s excellent for getting rapid feedback on code correctness while actively programming.

To compile (if needed) and immediately execute your program’s main binary:

cargo run

By default, cargo run uses the debug profile. To compile and run using the optimized release profile, simply add the flag:

cargo run --release

Finally, to compile your code (including test functions) and execute the tests:

cargo test

This command specifically looks for functions annotated as tests within your codebase, builds the necessary test executable(s), runs them, and reports the results (pass or fail).

Using these Cargo commands significantly simplifies the development cycle compared to invoking the compiler manually. Cargo handles finding source files, calling rustc with appropriate flags, and performs incremental compilation to speed up subsequent builds. During development, cargo check and debug builds (cargo build, cargo run) offer fast feedback, while cargo test ensures correctness, and release builds (--release) are used for performance testing and deployment.

4.2.3 Managing Dependencies (Crates)

Adding external libraries (crates) is a core function of Cargo. Dependencies are declared in the Cargo.toml file under the [dependencies] section. For example, to use the rand crate for random number generation:

# In Cargo.toml
[dependencies]
rand = "0.9" # Specify the desired version (Semantic Versioning is used)

Alternatively, you can use the command line:

cargo add rand # Fetches the latest compatible version and adds it to Cargo.toml
# Or specify a version:
cargo add rand --version 0.9

When you next run cargo build (or cargo run, cargo check, cargo test), Cargo performs the following steps:

  1. Reads Cargo.toml to identify required dependencies.
  2. Consults the Cargo.lock file (automatically generated) to ensure reproducible builds using specific dependency versions. If necessary, it resolves version requirements.
  3. Downloads the source code for any missing dependencies (including transitive dependencies – the dependencies of your dependencies) from crates.io.
  4. Compiles each dependency.
  5. Compiles your project code, linking against the compiled dependencies.

This integrated dependency management is a significant advantage compared to traditional C/C++ workflows, which often require manual library management or external package managers like Conan or vcpkg.

4.2.4 Additional Development Tools

Cargo integrates seamlessly with other tools in the Rust ecosystem, often installable via rustup (the Rust toolchain installer):

Note: If rustfmt or Clippy is not installed, run rustup component add rustfmt or rustup component add clippy.

Using these tools regularly helps ensure your code is correct, idiomatic, well-formatted, and maintainable. Many IDEs and text editors with Rust support can automatically run cargo check, cargo fmt, or cargo clippy during development.

4.2.5 Understanding Cargo.toml

The Cargo.toml file is the central configuration file for a Cargo project. It uses the TOML (Tom’s Obvious, Minimal Language) format. Key sections include:

Cargo uses the information in this file to orchestrate the entire build process.


4.3 Summary

This chapter provided a functional overview of rustc and Cargo. You now have the basic tools to compile, run, and manage dependencies for Rust projects. For more advanced topics like workspaces, custom build configurations, publishing crates, and features, refer to Chapter 23 and the official documentation.

4.3.1 Further Resources



| Contents |