Hello, Cargo!
Cargo is Rust's excellent build system and package manager, and it makes Rust projects much easier to manage. You can use Cargo to create new projects, build them, test them, and distribute them. The good news is that Cargo works seamlessly with Oxide—.ox files are treated identically to .rs files. Oxide benefits directly from Cargo's powerful tooling and ecosystem.
What is Cargo?
Cargo handles several important tasks for you:
- Building your code with
cargo build - Running your code with
cargo run - Testing your code with
cargo test - Generating documentation with
cargo doc - Publishing libraries to crates.io
- Managing dependencies through
Cargo.toml
Without Cargo, you'd need to manually compile your code with rustc, manage compilation flags, handle dependencies by hand, and coordinate all these tasks yourself. With Cargo, everything is automated and standardized.
Creating an Oxide Project
To create a new Oxide project, use Cargo with the --oxide flag:
$ cargo new --oxide hello_oxide
Created binary (application) `hello_oxide` package
$ cd hello_oxide
This generates an Oxide project with src/main.ox containing:
fn main() {
println!("Hello, world!")
}
Development Status: Oxide v1.0 is currently in development. The
--oxideflag will be available in Cargo once the Oxide toolchain is released. For early testing before the release, you can manually create a project withcargo newand renamesrc/main.rstosrc/main.ox.
Let's see what Cargo generated:
$ cd hello_oxide
$ ls -la
drwxr-xr-x .git
drwxr-xr-x .gitignore
-rw-r--r-- Cargo.toml
drwxr-xr-x src
Let's look at the directory structure:
$ tree .
.
├── Cargo.toml
└── src
└── main.ox
Understanding Cargo.toml
The Cargo.toml file is the manifest for your project. It contains metadata about your package and its dependencies. Here's what was created for us:
[package]
name = "hello_oxide"
version = "0.1.0"
edition = "2021"
[dependencies]
The [package] section contains metadata:
- name: The name of your project
- version: The current version of your code
- edition: The Rust edition (Oxide projects use the same editions as Rust)
The [dependencies] section is where you'd list any external crates your project depends on. We don't have any dependencies yet.
Understanding the src Directory
Cargo expects your source files to be in the src directory. With the --oxide flag, Cargo creates main.ox with a simple "Hello, World!" program:
fn main() {
println!("Hello, world!")
}
This is valid Oxide code that compiles and runs just like Rust. Let's make it feel more Oxide-like by using string interpolation:
fn main() {
let language = "Oxide"
println!("Hello from \(language)!")
}
The differences from the original:
- Added a variable to demonstrate Oxide's string interpolation:
"\(language)" - Omitted semicolons (optional in Oxide)
- The
fn main()andprintln!()syntax work identically in both Oxide and Rust
Building and Running Your Oxide Project
Now let's build the project using Cargo:
$ cargo build
Compiling hello_oxide v0.1.0
Finished dev [unoptimized + debuginfo] target/debug/hello_oxide
Congratulations! You've successfully compiled your first Oxide program with Cargo. The executable has been created in target/debug/hello_oxide (or target/debug/hello_oxide.exe on Windows).
To run it, use cargo run:
$ cargo run
Compiling hello_oxide v0.1.0
Finished dev [unoptimized + debuginfo] target/debug/hello_oxide
Running `target/debug/hello_oxide`
Hello, Oxide!
The cargo run command compiles the code and then runs the resulting executable—all in one command. It's very convenient for projects you're actively working on.
A Note About Cargo.lock
When you first build your project, Cargo creates a Cargo.lock file. This file keeps track of the exact versions of dependencies you've built with. For binary projects (like this one), you should commit Cargo.lock to version control so everyone working on the project uses the same dependency versions. For libraries, it's typically not committed.
Cargo Check
If you want to verify that your code compiles without actually producing an executable, you can use cargo check:
$ cargo check
Checking hello_oxide v0.1.0
Finished dev [unoptimized + debuginfo] target/debug/hello_oxide
This command is much faster than cargo build because it stops after type-checking and doesn't generate code. It's perfect for getting quick feedback as you're writing code.
Using Cargo with Mixed Oxide and Rust
One powerful feature of Oxide is that you can freely mix .ox and .rs files in the same Cargo project. Cargo doesn't care which extension you use—both are compiled and linked together seamlessly.
For example, if you have existing Rust code you want to reuse, or if you're gradually migrating a project to Oxide, you can simply keep both file types in the same src/ directory:
src/
├── main.ox # Oxide code
├── utils.rs # Rust code
├── lib.ox # Oxide library code
└── integrations.rs # Rust integrations
Cargo will compile all of them together:
$ cargo build
Compiling hello_oxide v0.1.0
Finished dev [unoptimized + debuginfo] target/debug/hello_oxide
You can call Rust functions from Oxide and vice versa—they're compiled to the same intermediate representation and linked together. This makes it easy to adopt Oxide incrementally.
Thinking in Terms of Cargo
As you work with Rust and Oxide projects, here's a mental model for Cargo:
Cargo is to systems programming as npm is to Node.js or pip is to Python. It's the standard way projects are organized, built, and distributed. Rust's community designed Cargo exceptionally well, and Oxide benefits from this thoughtful tooling.
Every Rust and Oxide project you'll encounter follows the same structure:
- Source code in
src/ - Dependencies listed in
Cargo.toml - Binaries in
target/debug/ortarget/release/ - Tests alongside your source code
Learning Cargo now means you'll immediately understand the structure of any Rust or Oxide project you encounter. This standardization is one of Rust's great strengths.
Building for Release
So far, we've been building in development mode with cargo build. This mode is great for development because compilation is fast and includes debug information. However, it doesn't optimize your code, so the resulting executable is slower.
When you're ready to ship your code, or when you care about performance, use the --release flag:
$ cargo build --release
Compiling hello_oxide v0.1.0
Finished release [optimized] target/release/hello_oxide
The executable will be in target/release/hello_oxide. Release builds take longer to compile but run much faster. You can also use:
$ cargo run --release
Compiling hello_oxide v0.1.0
Finished release [optimized] target/release/hello_oxide
Running `target/release/hello_oxide`
Hello, Oxide!
For benchmarking or production deployment, always use --release.
Summary
Congratulations! You've learned the basics of working with Cargo and Oxide:
- Cargo new creates a new project structure
- Cargo build compiles your project
- Cargo run compiles and runs your project
- Cargo check quickly verifies your code compiles
.oxfiles work seamlessly with Cargo just like.rsfiles- Mixed projects are fully supported—use both
.oxand.rsfiles in the same crate - Release builds provide optimizations for production use
You now have everything you need to start building Oxide projects. In the next chapter, we'll explore the fundamental concepts of the language itself.