Now that we've embarked on our Rust programming journey and mastered the art of writing a Hello World program from the command line, it's time to delve into Cargo – Rust's package manager and build system. In this blog post, we'll not only explore the reasons why Cargo is a game-changer but also provide a hands-on guide on how to leverage its features effectively.
Why Choose Cargo?
Before we dive into the how, let's quickly recap why Cargo is an essential tool for Rust developers:
Dependency Management: Cargo simplifies the process of adding and managing dependencies, ensuring a smooth integration of external libraries into your projects.
Consistent Project Structure: Cargo generates a standardized project structure, fostering consistency and making collaboration more accessible.
Efficient Build Process: With a single command,
cargo build
, you can compile your code, handle dependencies, and build your project effortlessly.Automated Testing: Cargo integrates seamlessly with Rust's testing framework, allowing you to run tests with a simple
cargo test
command.Easy Distribution: Cargo provides a streamlined way to package and distribute your Rust projects, making it convenient for both developers and users.
Now, let's get hands-on with Cargo.
Getting Started with Cargo:
Cargo comes installed with Rust if you used the official installers discussed in the previous blog, if not then you can click here for a smooth setup. Check whether Cargo is installed by entering the following in your terminal:
$ cargo --version
If you see a version number, you have it! if not please go ahead and install it.
1. Creating a New Rust Project:
To initialize a new Rust project, use the following command:
cargo new my_project
cd my_project
This will create a new directory named my_project
with the standard project structure.
2. Adding Dependencies:
Open the Cargo.toml
file in your project directory. This file serves as the configuration file for your project. To add a dependency, modify the [dependencies]
section. For example:
[package]
name = "my_project"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rand = "0.8.5"
# Rand provides utilities to generate random numbers, to convert them to useful types and distributions, and some randomness-related algorithms.
Run cargo build
to fetch and compile the specified dependencies. For now we don't need to add any dependencies but for future projects this is the place to add dependencies.
3. Building and Running a Cargo Project:
Let's take a look at src/main.rs
file:
fn main() {
println!("Hello, world!");
}
Cargo has generated a “Hello, world!” program, just like the one we've written in the previous blog. Key differences are:
Cargo placed the code in the src directory.
We've a Cargo.toml configuration file in the top directory.
In the Cargo convention, our source files are anticipated to reside within the src directory. The primary project directory is designated for README files, license information, configuration files, and any other content unrelated to our actual code.
As we've seen previously that in rust compiling and running are two differenet steps. For that in cargo we've the command cargo build
:
$ cargo build
Compiling hello_cargo v0.1.0 (file:///projects/my_project)
Finished dev [unoptimized + debuginfo] target(s) in 2.85 secs
When you run this command, an executable file is created in target/debug/my_project (or target\debug\my_project.exe on Windows)
, not in your current directory. Since it's a default debug build, Cargo puts the binary in a debug directory. To run the executable, use this command:
$ ./target/debug/my_project # or .\target\debug\my_project.exe on Windows
Hello, world!
After constructing our project using cargo build
and executing it with ./target/debug/my_project
, there's an alternative approach. You can streamline the process by using cargo run
, which compiles the code and immediately executes the resulting executable in a single command:
$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
Running `target/debug/my_project`
Hello, world!
Opting for cargo run
is more convenient compared to the two-step process of remembering to run cargo build
and then specifying the full path to the binary. Hence, the majority of developers prefer the simplicity of cargo run
.
It's noteworthy that this time, no output indicated that Cargo was compiling my_project
. Cargo intelligently recognized that the files hadn't undergone any changes, opting to run the existing binary rather than initiating a rebuild. If modifications were made to the source code, Cargo would have executed a rebuild before running.
Cargo also furnishes a command named cargo check
. This command swiftly verifies your code for compilation correctness without generating an executable:
$ cargo check
Checking hello_cargo v0.1.0 (file:///projects/my_project)
Finished dev [unoptimized + debuginfo] target(s) in 0.32 secs
Why might you opt not to generate an executable? Frequently, cargo check
proves significantly faster than cargo build
since it bypasses the step of creating an executable. If you find yourself consistently checking your work during the coding process, employing cargo check
expedites the feedback loop, promptly notifying you if your project is still compiling. Many Rust developers intermittently run cargo check
as they code to ensure compilation correctness, reserving cargo build
for when they're prepared to generate the executable.
4. Building for Release
When your project is prepared for its final release, employ cargo build --release
to compile it with optimizations. This command produces an executable in target/release
rather than target/debug
. While these optimizations enhance the runtime performance of your Rust code, it's essential to note that enabling them prolongs the compilation time of your program.
To accommodate different needs, Cargo provides two distinct profiles: one tailored for development, facilitating quick and frequent rebuilds, and another optimized for constructing the final program intended for users. This final version is designed for optimal runtime speed and is not subjected to repeated rebuilds.
For accurate benchmarking of your code's execution time, ensure to execute cargo build --release
and conduct benchmarks using the resulting executable in the target/release
directory.
Summary
Cargo is more than just a package manager – it's a versatile tool that significantly improves the Rust development experience. As we continue our Rust journey, we'll explore more advanced Cargo features, and leverage its power to streamline our workflow. Let's summarize the key points we've covered about Cargo:
- Initiating a new project is accomplished with
cargo new
. - Building a project is executed via
cargo build
. - The combined process of building and running a project can be streamlined with
cargo run
. - Conducting a swift code check for errors, without producing an executable, is achieved using
cargo check
. - Cargo stores build results in the
target/debug
directory, diverging from the project's source code directory. - For optimal performance in a release-ready project, utilize
cargo build --release
. - A noteworthy advantage of Cargo is its cross-platform consistency, where commands remain the same regardless of the operating system.
Thanks for reading, i hope it was worth your time. Happy coding!
Top comments (0)