diff --git a/src/SUMMARY.md b/src/SUMMARY.md index c3add55d48..7b07e9f3b0 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -82,6 +82,11 @@ - [Library](crates/lib.md) - [`extern crate`](crates/link.md) +- [Cargo](cargo.md) + - [Dependencies](cargo/deps.md) + - [Conventions](cargo/conventions.md) + - [Tests](cargo/test.md) + - [Attributes](attribute.md) - [`dead_code`](attribute/unused.md) - [Crates](attribute/crate.md) diff --git a/src/cargo.md b/src/cargo.md new file mode 100644 index 0000000000..d312a53ba4 --- /dev/null +++ b/src/cargo.md @@ -0,0 +1,12 @@ +# Cargo + +`cargo` is the official Rust package management tool. It has lots of really +useful features to improve code quality and developer velocity! These include + +- Dependency management and integration with [crates.io](https://crates.io) (the + official Rust package registry) +- Awareness of unit tests +- Awareness of benchmarks + +This chapter will go through some quick basics, but you can find the +comprehensive docs [here](http://doc.crates.io/index.html). diff --git a/src/cargo/conventions.md b/src/cargo/conventions.md new file mode 100644 index 0000000000..ae7cab0d83 --- /dev/null +++ b/src/cargo/conventions.md @@ -0,0 +1,36 @@ +# Conventions + +In the previous chapter, we saw the following directory heirarcy: + +```txt +foo +├── Cargo.toml +└── src + └── main.rs +``` + +Suppose that we wanted to have two binaries in the same project, though. What +then? + +It turns out that cargo supports this. The default binary name is `main.rs`, as +we saw before, but you can add additional binaries by placing them in a `bin/` +directory: + +```txt +foo +├── Cargo.toml +└── src + ├── main.rs + └── bin + └── my_other_bin.rs +``` + +To tell cargo to compile or run this binary as opposed to the default or other +binaries, we just pass cargo the `--bin my_other_bin` flag, where `my_other_bin` +is the name of the binary we want to work with. + +In addition to extra binaries, there is support for benchmarks, tests, and +examples. The full capaibilities are documented +[here](http://doc.crates.io/book/guide/project-layout.html). + +In the next chapter, we will look more closely at tests. diff --git a/src/cargo/deps.md b/src/cargo/deps.md new file mode 100644 index 0000000000..6115e771e9 --- /dev/null +++ b/src/cargo/deps.md @@ -0,0 +1,88 @@ +# Dependencies + +Most programs have dependencies on some libraries. If you have ever managed +dependencies by hand, you know how much of a pain this. Luckily, the Rust +ecosystem comes standard with `cargo`! `cargo` can manage dependcies for a +project. + +To create a new Rust project, + +```sh +# A binary +cargo new --bin foo + +# OR A library +cargo new foo +``` + +For the rest of this chapter, I will assume we are making a binary, rather than +a library, but all of the concepts are the same. + +After the above commands, you should see something like this: + +```txt +foo +├── Cargo.toml +└── src + └── main.rs +``` + +The `main.rs` is the root source file for your new project -- nothing new there. +The `Cargo.toml` is the config file for `cargo` for this project (`foo`). If you +look inside it, you should see something like this: + +```toml +[package] +name = "foo" +version = "0.1.0" +authors = ["mark"] + +[dependencies] +``` + +You can read more extensively about all of the available configuration options +[here](http://doc.crates.io/manifest.html). + +The `name` field under `package` determines the name of the project. This is +used by `crates.io` if you publish the crate (more later). It is also the name +of the output binary when you compile. + +The `version` field is a crate version number using [Semantic +Versioning](http://semver.org/). + +The `authors` field is a list of authors used when publishing the crate. + +The `dependencies` section lets you add a dependency for your project. + +For example, suppose that I want my program to have a great CLI. You can find +lots of great packages on [crates.io](https://crates.io) (the official Rust +package registry). One popular choice is [clap](https://crates.io/crates/clap). +As of this writing, the most recent published version of `clap` is `2.27.1`. To +add a dependency to our program, we can simply add the following to our +`Cargo.toml` under `dependencies`: `clap = "2.27.1"`. And of course, `extern +crate clap` in `main.rs`, just like normal. And that's it! You can start using +`clap` in your program. + +`cargo` also supports other types of dependencies. Here is just a small +sampling. You can find out more +[here](http://doc.crates.io/specifying-dependencies.html). + +```toml +[package] +name = "foo" +version = "0.1.0" +authors = ["mark"] + +[dependencies] +clap = "2.27.1" # from crates.io +rand = { git = "https://github.com/rust-lang-nursery/rand" } # from online repo +bar = { path = "../bar" } # from a path in the local filesystem +``` + +To build our project we can execute `cargo build` anywhere in the project +directory (including subdirectories!). We can also do `cargo run` to build and +run. Notice that these commands will resolve all dependencies, download crates +if needed, and build everything, including your crate. (Note that it only +rebuilds what it has not already built, similar to `make`). + +Voila! That's all there is too it! diff --git a/src/cargo/test.md b/src/cargo/test.md new file mode 100644 index 0000000000..9d31f8654e --- /dev/null +++ b/src/cargo/test.md @@ -0,0 +1,69 @@ +# Testing + +As we know testing is integral to any piece of software! Rust has first-class +support for unit and integration testing ([see that chapter for +more](https://rustbyexample.com/meta/test.html); or [this +chapter](https://doc.rust-lang.org/book/second-edition/ch11-00-testing.html) in +TRPL). + +From the testing chapters linked above, we see how to write unit tests and +integration tests. Organizationally, we can place unit tests in the modules they +test and integration tests in their own `tests/` directory: + +```txt +foo +├── Cargo.toml +├── src +│ └── main.rs +└── tests + ├── my_test.rs + └── my_other_test.rs +``` + +Each file in `tests` is a separate integration test. + +`cargo` naturally provides an easy way to run all of your tests! + +```sh +cargo test +``` + +You should see output like this: + +```txt +$ cargo test + Compiling blah v0.1.0 (file:///nobackup/blah) + Finished dev [unoptimized + debuginfo] target(s) in 0.89 secs + Running target/debug/deps/blah-d3b32b97275ec472 + +running 3 tests +test test_bar ... ok +test test_baz ... ok +test test_foo_bar ... ok +test test_foo ... ok + +test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out +``` + +You can also run tests whose name matches a pattern: + +```sh +cargo test test_foo +``` + +```txt +$ cargo test test_foo + Compiling blah v0.1.0 (file:///nobackup/blah) + Finished dev [unoptimized + debuginfo] target(s) in 0.35 secs + Running target/debug/deps/blah-d3b32b97275ec472 + +running 2 tests +test test_foo ... ok +test test_foo_bar ... ok + +test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 2 filtered out +``` + +One word of caution: Cargo may run multiple tests concurrently, so make sure +that they don't race with each other. For example, if they all output to a +file, you should make them write to different files.