Cargo

Cargo is rust's build and dependency management system. It is similar to gradle and maven in Java. However in comparison to them Cargo is much simpler. For example Cargo uses the TOML file format for it's config, which is written in a declaritive style.

For example you might write:

[package]
name = "hello_world"
version = "0.0.1"
authors = ["Your Name <you@example.com>"]
edition = "2018"

[dependencies]
snafu = "0.6.8"
serde = "1.0"
# This is a comment ...

You can find more information about cargo in the cargo book

Some common commands are listed below:

CommandEffect
cargo new --bin fooCreate a new program named "foo"
cargo new --lib fooCreate a new library named "foo"
cargo buildBuild the current project
cargo cleanCleans the build directory
cargo checkChecks for complication errors
cargo docBuilds Rustdocs
cargo testRuns tests (Like Junit, but built into the language)
cargo publishPublish the crate to Crates.io
  • https://blog.rust-lang.org/2016/05/05/cargo-pillars.html
  • Toml format
  • Dependencies
    • Dev-Dependencies
  • Cargo tools
    • Audit
    • Doc test

Versions

  • Depreciation warning

One old idea that Rust embraces is versioning. Unlike Java (or most other programming languages) in Rust when creating a new project you explicitly specify which edition of the language you wish use. This Book is written to the 2018 edition of the language. This edition has different syntax than the 2015 edition, and future editions will change things as well. But backwards compatibility is maintained because the compiler can check which edition is being used and compile to that standard. Because regardless of which edition is being used the code is compiled to native code, code written in any edition can depend on code written in any other edition. This frees the language to evolve and change overtime without being tied down to legacy.

Similarly in Rust all projects are expected to use semantic versioning of the form Major.Minor.Patch where a change to the patch version means no publicly visible changes have occurred, a change to the minor version means changes have occurred but existing code should still work, and a change to the major version means dependant code needs to be re-written. Changes that break backwards compatibility are also OK prior to a 1.0.0 version.

The Rust language itself also versioned in this way. This is actually how Java was originally versioned. They released 1.2, 1.3, 1.4, and 1.5. But then they decided that they could drop the leading 1 because they were not going to break compatibility. Just looking at the version number you can see that Rust releases a lot faster than Java. The Language is on a six-week release cycle so it's constantly improving.

This rapid release cycle is made possible because it is well factored in well tested. Most of what would be considered the standard library in another language is packaged and released separately. The developers even have a tool which will build all publicly available code against a new version of the language before it is released.

Unlike Java, Rust has a very small standard library. Instead it provides powerful and flexible primitives, that allow many features you wouldn’t expect to be developed as libraries. This works because Rust has a built in dependency management system called Cargo.

Dependencies

Dependencies can be added to your project by simply addin the approprate line in Cargo.toml. To find crates you can depend on and the line to add them to your config file go to crates.io.

Unlike Java, you don't need to worry about transitive dependencies, it is not possible to endup accedently directly using their code, and "version conflicts" are not an issue, because multiple versions can be in the same application at the same time without ambiguity.

Below is a list of common dependencies and their function.

CrateFunction
SerdeSerialization and Deserialization
ClapCommand line argument parsing. (See also structopt which automates even more
Simple-signalUnix signal handling
BindgenAutomatically generates Rust FFI bindings to C
ItertoolsExtra iterator adaptors and methods
RayonSimple lightweight data-parallelism library
FasterSMID made safe and simple using iterators
Packed-simdArchitecture independent SIMD
CrossbeamTools for concurrent programming
TokioA non-blocking IO framework
DieselA compile time validated ORM query buider
RocketA web server that uses compile time checks to prevent vunribilites (directory traversal, SQL injection, csrf, css, remote code execution, misconfiguration) and verifies authentication, authorization, and input validation logic.
MaudCompile time validated HTML templates
RandRandom number generators
QuickcheckRandomized unit testing
  • Logging of events for metrics

  • Rtfm for embedded systems. Also Singleton. And svd2rust

  • Instead of rolling your own graph: Petgraph or an ECS

  • Rustfmt/racer/rustfix

  • Rustup

  • Cargo

  • Rr

  • Fuzzers

    • Cargo fuzz uses an address checker to verify uninitialized memory is not being read.
    • Angora - Still a work in progress, but should eventually be the best fuzzer.
  • Habitat

  • Servo

  • redox

  • Ripgrep

Below are some common dependencies and a brief description of what they do: High precision math and units IoUtils Builder equals, hash, and serializable Log slog Similar to Junit Benchmark / criterion Example testing Quick check / propcheck Checksyle Findbugs Lint (clippy) Fuzzers: afl / hongfuzz / cargo fuzz

Rustc

If you've been programming in Java for a long time you're probably used to compiler-errors that you just look at to get the line number and then go to the that line and see what's wrong. IDEs have mostly even obsoleted this by just underlining the problem, which is usually sufficient to work out the problem. Rust goes well above and beyond this. It has very clear and detailed error messages explaining exactly what the problem is some of which even suggest Solutions what's more each error message has a number associated with it but you can look up online and see if full documentation as to why that error message occurs examples of it occurring how to avoid it and how to structure code so is to prevent it from being a problem.