Introduction to Rust. A C++ Engineer perceptive (Tooling)
Welcome to the out new article of our Rust series, custom-tailored for C++ developers eager to broaden their skill set! In this chapter, we’ll delve into the critical aspects of tooling in Rust programming. While this element may not be an part of the programming language itself, it is undoubtedly essential component of any robust and efficient programming workflow.
Buckle up as we explore the tools that make Rust development a breeze, ensuring the reliability and correctness of our Rust programs. Together, we’ll master the art of harnessing Rust’s full potential for building high-quality software.
Tooling
Rust boasts a thriving ecosystem of tooling that continues to grow, offering developers a wide array of resources and utilities. In this article, we will zoom in on two fundamental tools that are essential for kickstarting your journey into Rust system development, the compiler and the package manager.
Compiler
The first and foremost tool in the Rust ecosystem is the Rust compiler itself, that when compared with the GCC is more restrictive by default. The Rust compiler is the responsible for transforming our human-readable Rust code into machine-executable binary code. It plays a pivotal role in enforcing the language’s strong guarantees related to memory safety, concurrency, and overall correctness.
Rust’s compiler has a lot powerful features, such as the borrow checker and the ownership system. These features ensure that our code is free from common memory-related bugs like null pointer dereferences, use-after-free, and data races, providing a high level of confidence in the safety and reliability of our programs, what related with the memory section on our first article.
Another bonus of the Rust compiler it’s the proactive approach to treat data races in concurrent programming, aiming to eliminate them. Given that data races occur when two or more threads access the same data concurrently, that can lead to undefined behavior, the compile enforces strict rules through its ownership and borrowing system.
The ownership model ensures that each piece of data has a single owner at any given time, and when shared access to data is required, the borrowing system allow multiple references to read the data simultaneously. However, Rust’s rules prevent multiple mutable references to the same data, ensuring that data races cannot occur through mutable aliasing.
As a really good bonus is that the error messages and diagnostics, are easy to understand, and really help to write code that adheres to Rust’s strict rules and best practices.
Cargo - Rust Package Manager
Rust has a growing and vibrant ecosystem of packages and library, that is most given to it’s package manager called Cargo. Cargo makes it easy to manage dependencies, build projects, run tests, and sharing it with the community.
The first function of Cargo is to provide a seamless project creation experience in Rust, ensuring a well-known and standardized structure for every Rust project. By establishing a consistent project layout, Cargo simplifies navigation and fosters an environment where developers can easily dive into any Rust project with confidence.
To do that is just necessary to use the follow commands:
cargo new my_rust_project
This will create a folder with the follow structure:
.:
total 4
-rw-r--r--. 1 vitor vitor 184 Jul 31 12:00 Cargo.toml
drwxr-xr-x. 1 vitor vitor 14 Jul 31 12:00 src
./src:
total 4
-rw-r--r--. 1 vitor vitor 45 Jul 31 12:00 main.rs
However the main function of the cargo is to allow the developers to easily add dependencies to their projects, and handles the entire dependency resolution process, ensuring a smooth and hassle-free experience. This allows developers to focus on building their applications without worrying about version conflicts or manual dependency management.
The process of add a dependency on a project is given by the simple command:
cargo add my_dependecy_name --version "x.x.x"
This will add the dependency in the Cargo.toml file, that is a manifest of your project.
[package]
name = "my_rust_project"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
my_dependecy_name = "x.x.x"
Conclusion
As we conclude our exploration of Rust’s tooling, it becomes evident that Rust offers a complete and powerful toolset that empowers developers throughout their entire development workflow.
From the moment we create a new project using Cargo, Rust sets a strong foundation with its standardized project structure, allowing for seamless navigation and consistent development practices. Cargo’s package management capabilities streamline the process of adding and managing dependencies, ensuring that our projects are built on reliable and up-to-date components.
Rust’s compiler, backed by the borrow checker, is a formidable ally in the battle against bugs and memory-related issues. It enforces strict rules and safety guarantees, catching potential issues at compile-time and reducing the likelihood of runtime errors
Additionally, Rust has excellent documentation and an active community that is always ready to help you with any questions or issues you may have.
As always is possible to go deeper this topic, by the Rust documentation, mainly with the Rust Programming Book, that is a amazing reference tool.