Skip to content

Latest commit

 

History

History
329 lines (281 loc) · 7.59 KB

File metadata and controls

329 lines (281 loc) · 7.59 KB
title Crates and Packages
slug crates-and-Packages

Crate

  • A crate is the smallest unit of compilation in Rust.

  • A crate compiles as a single unit. If it contains modules in separate files, the compiler builds an isolated module tree starting from the crate root before compilation.

  • Each crate maintains its own module tree rooted at the crate root:

    • Binary crates: src/main.rs or a .rs file in the src/bin/ directory
    • Library crates: Usually src/lib.rs
  • Main crate types are,

    Type Description
    bin Executable program
    lib Let the compiler decide the library type. Defaults to rlib
    rlib Static library for linking into other Rust crates.
    staticlib Static library for linking into non-Rust programs
    dylib Rust dynamic library (rarely used)
    cdylib Dynamic library for C/FFI and other non-Rust programs
    proc-macro Library crate that defines procedural macros

    [!tip] To configure the library crate type/ types, we can use the [lib] section of Cargo.toml.

    [lib]
    crate-type = ["rlib", "cdylib"] // Rust library + C-compatible dynamic library

Package

  • A package is a Cargo project containing one or more crates, described by a Cargo.toml manifest.
  • A Cargo package can contain:
    • Zero or more binary crates
    • Zero or one library crate
  • Typical package layouts are,
    • src/main.rs: A package with single binary crate.
    • src/lib.rs: A package with single library crate.
    • src/bin/*.rs: A package with multiple binary crates.
    • src/main.rs + src/lib.rs: A package with 1 binary crate + 1 library crate.
    • src/bin/*.rs + src/lib.rs: A package with multiple binary crates + 1 library crate.

Common Package Layouts

Single Binary

my_app
├── Cargo.toml
└── src
    └── main.rs

[!lab]

cargo new my_app
cd my_app && cargo run

Single Library

my_app
├── Cargo.toml
└── src
    └── lib.rs

[!lab]

cargo new my_app --lib
cd my_app && cargo test

Single Binary + Single Library

my_app
├── Cargo.toml
└── src
    ├── lib.rs
    └── main.rs

{{< tabs count=3 label="Select File" >}} {{< tab label="lib.rs" >}}

pub fn greet() {
    println!("Hello Lib!");
}

{{< /tab >}} {{< tab label="main.rs" >}}

fn main() {
    my_app::greet();
}

{{< /tab >}} {{< tab label="Cargo.toml" >}}

[package]
name = "my_app"
version = "0.1.0"
edition = "2024"

[dependencies]

{{< /tab >}} {{< /tabs >}}

[!lab]

cargo new my_app
cd my_app && touch src/lib.rs
$copy above file content
cargo run

Multiple Binary

my_app
├── Cargo.toml
└── src
    └── bin
        ├── app.rs
        └── cli.rs

{{< tabs count=3 label="Select File" >}} {{< tab label="app.rs" >}}

pub fn greet() {
    println!("Hello App!");
}

{{< /tab >}} {{< tab label="cli.rs" >}}

pub fn greet() {
    println!("Hello Cli!");
}

{{< /tab >}} {{< tab label="Cargo.toml" >}}

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

[[bin]]
name = "app"
path = "src/bin/app.rs"

[[bin]]
name = "cli"
path = "src/bin/cli.rs"

[dependencies]

{{< /tab >}} {{< /tabs >}}

[!lab]

cargo new my_app && cd my_app
mkdir src/bin && mv src/main.rs src/bin/app.rs && cp src/bin/app.rs src/bin/cli.rs
$copy above file content
  • Run app binary crate: cargo run --bin app / cargo run (as Cargo.toml -> default-run = "app")
  • Run cli binary crate: cargo run --bin cli

Multiple Binary + Single Library

my_app
├── Cargo.toml
└── src
    ├── bin
    │   ├── app.rs
    │   └── cli.rs
    └── lib.rs

[!assignment]

cargo new my_app --lib && cd my_app
mkdir -p src/bin && touch src/bin/app.rs src/bin/cli.rs
$write sample file content

Adding Dependencies

  • A project dependency can be added from:
    • crates.io - Rust's official package registry
    • A Git repository
    • A folder path

[!tip] Tip: cargo add <PACKAGE>

  • -n / --dry-run: Preview changes without modifying Cargo.toml. Ex: cargo add uuid -n
  • -F / --features <FEATURES>: Enable specific features. Ex: cargo add uuid -F v7,fast-rng
    • uuid = { version = "1.23.4", features = ["v7", "fast-rng"] } (💡Cargo.toml [dependencies])
  • --rename <NAME>: Rename the dependency. Ex. cargo add uuid --rename id
    • id = { version = "1.23.4", package = "uuid" } (💡Cargo.toml [dependencies])
  • Source: A Git repository
    • --git <URI>: Git repository location.
    • --branch <BRANCH>: Git branch to download the crate from
    • --tag <TAG>: Git tag to download the crate from.
    • --rev <REV>: Git reference to download the crate from
    • Ex.
      • cargo add uuid --git https://github.com/uuid-rs/uuid
      • cargo add uuid --git https://github.com/uuid-rs/uuid --tag v1.23.4
  • Source: A local crate
    • --path <PATH>: Filesystem path to local crate to add
    • Ex. cargo add foo --path foo (💡my_app/foo/)

From crates.io

[!lab]

cargo new my_app && cd my_app
cargo add uuid -F v7
$copy main.rs file content
cargo run

{{< tabs count=2 label="Select File" >}} {{< tab label="main.rs" >}}

use uuid::Uuid;

fn main() {
    println!("{}", Uuid::now_v7());
}

{{< /tab >}} {{< tab label="Cargo.toml" >}}

[package]
name = "my_app"
version = "0.1.0"
edition = "2024"

[dependencies]
uuid = { version = "1.23.4", features = ["v7"] }

{{< /tab >}} {{< /tabs >}}

From a Git Repository

[!lab]

cargo new my_app && cd my_app
cargo add uuid --git https://github.com/uuid-rs/uuid --tag v1.23.4 -F v7
$copy main.rs file content
cargo run

{{< tabs count=2 label="Select File" >}} {{< tab label="main.rs" >}}

use uuid::Uuid;

fn main() {
    println!("{}", Uuid::now_v7());
}

{{< /tab >}} {{< tab label="Cargo.toml" >}}

[package]
name = "my_app"
version = "0.1.0"
edition = "2024"

[dependencies]
uuid = { git = "https://github.com/uuid-rs/uuid", tag = "v1.23.4", version = "1.23.4", features = ["v7"] }

{{< /tab >}} {{< /tabs >}}

From a Local Crate

[!lab]

cargo new my_app && cd my_app
cargo new foo --lib
cargo add foo --path foo
$copy my_app/foo/src/lib.rs and my_app/src/main.rs file content
cargo run

{{< tabs count=3 label="Select File" >}} {{< tab label="foo/src/lib.rs" >}}

pub fn greet() {
    println!("Hello Foo");
}

{{< /tab >}} {{< tab label="src/main.rs" >}}

use foo;

fn main() {
    foo::greet();
}

{{< /tab >}} {{< tab label="Cargo.toml" >}}

[package]
name = "my_app6"
version = "0.1.0"
edition = "2024"

[dependencies]
foo = { version = "0.1.0", path = "foo" }

{{< /tab >}} {{< /tabs >}}