From 4d590f95434ab10a93c1c9f591d3599060d7f782 Mon Sep 17 00:00:00 2001 From: Behnam Esfahbod Date: Wed, 30 Aug 2017 15:38:51 -0700 Subject: [PATCH 01/22] [src/doc/book] Import from cargo-book repo --- src/doc/book/README.md | 47 ++ src/doc/book/src/01-01-installation.md | 21 + src/doc/book/src/01-02-first-steps.md | 70 ++ src/doc/book/src/02-01-why-cargo-exists.md | 11 + .../book/src/02-02-creating-a-new-project.md | 111 +++ .../02-03-working-on-an-existing-project.md | 22 + src/doc/book/src/02-04-dependencies.md | 90 +++ src/doc/book/src/02-05-project-layout.md | 136 ++++ src/doc/book/src/02-06-tests.md | 39 + .../book/src/02-07-continuous-integration.md | 21 + .../book/src/03-01-specifying-dependencies.md | 526 +++++++++++++ src/doc/book/src/03-02-manifest.md | 725 ++++++++++++++++++ src/doc/book/src/03-03-config.md | 136 ++++ .../book/src/03-04-environment-variables.md | 121 +++ src/doc/book/src/03-05-build-scripts.md | 536 +++++++++++++ src/doc/book/src/03-06-crates-io.md | 222 ++++++ src/doc/book/src/03-07-pkgid-spec.md | 44 ++ src/doc/book/src/03-08-source-replacement.md | 128 ++++ src/doc/book/src/03-09-external-tools.md | 102 +++ src/doc/book/src/03-10-policies.md | 52 ++ src/doc/book/src/SUMMARY.md | 25 + src/doc/book/src/cargo-in-depth.md | 4 + src/doc/book/src/faq.md | 193 +++++ src/doc/book/src/favicon.ico | Bin 0 -> 5430 bytes src/doc/book/src/getting-started.md | 4 + src/doc/book/src/guide.md | 21 + src/doc/book/src/images/Cargo-Logo-Small.png | Bin 0 -> 58168 bytes src/doc/book/src/images/auth-level-acl.png | Bin 0 -> 90300 bytes src/doc/book/src/images/forkme.png | Bin 0 -> 4725 bytes src/doc/book/src/images/org-level-acl.png | Bin 0 -> 76572 bytes 30 files changed, 3407 insertions(+) create mode 100644 src/doc/book/README.md create mode 100644 src/doc/book/src/01-01-installation.md create mode 100644 src/doc/book/src/01-02-first-steps.md create mode 100644 src/doc/book/src/02-01-why-cargo-exists.md create mode 100644 src/doc/book/src/02-02-creating-a-new-project.md create mode 100644 src/doc/book/src/02-03-working-on-an-existing-project.md create mode 100644 src/doc/book/src/02-04-dependencies.md create mode 100644 src/doc/book/src/02-05-project-layout.md create mode 100644 src/doc/book/src/02-06-tests.md create mode 100644 src/doc/book/src/02-07-continuous-integration.md create mode 100644 src/doc/book/src/03-01-specifying-dependencies.md create mode 100644 src/doc/book/src/03-02-manifest.md create mode 100644 src/doc/book/src/03-03-config.md create mode 100644 src/doc/book/src/03-04-environment-variables.md create mode 100644 src/doc/book/src/03-05-build-scripts.md create mode 100644 src/doc/book/src/03-06-crates-io.md create mode 100644 src/doc/book/src/03-07-pkgid-spec.md create mode 100644 src/doc/book/src/03-08-source-replacement.md create mode 100644 src/doc/book/src/03-09-external-tools.md create mode 100644 src/doc/book/src/03-10-policies.md create mode 100644 src/doc/book/src/SUMMARY.md create mode 100644 src/doc/book/src/cargo-in-depth.md create mode 100644 src/doc/book/src/faq.md create mode 100644 src/doc/book/src/favicon.ico create mode 100644 src/doc/book/src/getting-started.md create mode 100644 src/doc/book/src/guide.md create mode 100644 src/doc/book/src/images/Cargo-Logo-Small.png create mode 100644 src/doc/book/src/images/auth-level-acl.png create mode 100644 src/doc/book/src/images/forkme.png create mode 100644 src/doc/book/src/images/org-level-acl.png diff --git a/src/doc/book/README.md b/src/doc/book/README.md new file mode 100644 index 00000000000..af8d04a59ea --- /dev/null +++ b/src/doc/book/README.md @@ -0,0 +1,47 @@ +# The Cargo Book + + +### Requirements + +Building the book requires [mdBook]. To get it: + +[mdBook]: https://github.com/azerupi/mdBook + +```bash +$ cargo install mdbook +``` + +### Building + +To build the book: + +```bash +$ mdbook build +``` + +The output will be in the `book` subdirectory. To check it out, open it in +your web browser. + +_Firefox:_ +```bash +$ firefox book/index.html # Linux +$ open -a "Firefox" book/index.html # OS X +$ Start-Process "firefox.exe" .\book\index.html # Windows (PowerShell) +$ start firefox.exe .\book\index.html # Windows (Cmd) +``` + +_Chrome:_ +```bash +$ google-chrome book/index.html # Linux +$ open -a "Google Chrome" book/index.html # OS X +$ Start-Process "chrome.exe" .\book\index.html # Windows (PowerShell) +$ start chrome.exe .\book\index.html # Windows (Cmd) +``` + + +## Contributing + +Given that the book is still in a draft state, we'd love your help! Please feel free to open +issues about anything, and send in PRs for things you'd like to fix or change. If your change is +large, please open an issue first, so we can make sure that it's something we'd accept before you +go through the work of getting a PR together. diff --git a/src/doc/book/src/01-01-installation.md b/src/doc/book/src/01-01-installation.md new file mode 100644 index 00000000000..9f9052344cc --- /dev/null +++ b/src/doc/book/src/01-01-installation.md @@ -0,0 +1,21 @@ +## Installation + +The easiest way to get Cargo is to get the current stable release of Rust by +using the `rustup` script: + +```shell +$ curl -sSf https://static.rust-lang.org/rustup.sh | sh +``` + +This will get you the current stable release of Rust for your platform along +with the latest Cargo. + +If you are on Windows, you can directly download the latest stable Rust and nightly Cargo: + +- [Rust (32-bit)](https://static.rust-lang.org/dist/rust-1.17.0-i686-pc-windows-gnu.msi) +- [Cargo (32-bit)](https://static.rust-lang.org/cargo-dist/cargo-nightly-i686-pc-windows-gnu.tar.gz) + +- [Rust (64-bit)](https://static.rust-lang.org/dist/rust-1.17.0-x86_64-pc-windows-gnu.msi) +- [Cargo (64-bit)](https://static.rust-lang.org/cargo-dist/cargo-nightly-x86_64-pc-windows-gnu.tar.gz) + +Alternatively, you can [build Cargo from source](https://github.com/rust-lang/cargo#compiling-from-source). diff --git a/src/doc/book/src/01-02-first-steps.md b/src/doc/book/src/01-02-first-steps.md new file mode 100644 index 00000000000..974adecc5a4 --- /dev/null +++ b/src/doc/book/src/01-02-first-steps.md @@ -0,0 +1,70 @@ +## First steps with Cargo + +To start a new project with Cargo, use `cargo new`: + +```shell +$ cargo new hello_world --bin +``` + +We’re passing `--bin` because we’re making a binary program: if we +were making a library, we’d leave it off. + +Let’s check out what Cargo has generated for us: + +```shell +$ cd hello_world +$ tree . +. +├── Cargo.toml +└── src + └── main.rs + +1 directory, 2 files +``` + +This is all we need to get started. First, let’s check out `Cargo.toml`: + +```toml +[package] +name = "hello_world" +version = "0.1.0" +authors = ["Your Name "] +``` + +This is called a **manifest**, and it contains all of the metadata that Cargo +needs to compile your project. + +Here’s what’s in `src/main.rs`: + +``` +fn main() { + println!("Hello, world!"); +} +``` + +Cargo generated a “hello world” for us. Let’s compile it: + +```shell +$ cargo build + Compiling hello_world v0.1.0 (file:///path/to/project/hello_world) +``` + +And then run it: + +```shell +$ ./target/debug/hello_world +Hello, world! +``` + +We can also use `cargo run` to compile and then run it, all in one step: + +```shell +$ cargo run + Fresh hello_world v0.1.0 (file:///path/to/project/hello_world) + Running `target/hello_world` +Hello, world! +``` + +## Going further + +For more details on using Cargo, check out the [Cargo Guide](guide.html) diff --git a/src/doc/book/src/02-01-why-cargo-exists.md b/src/doc/book/src/02-01-why-cargo-exists.md new file mode 100644 index 00000000000..6f08a2f4e11 --- /dev/null +++ b/src/doc/book/src/02-01-why-cargo-exists.md @@ -0,0 +1,11 @@ +## Why Cargo exists + +Cargo is a tool that allows Rust projects to declare their various +dependencies and ensure that you’ll always get a repeatable build. + +To accomplish this goal, Cargo does four things: + +* Introduces two metadata files with various bits of project information. +* Fetches and builds your project’s dependencies. +* Invokes `rustc` or another build tool with the correct parameters to build your project. +* Introduces conventions to make working with Rust projects easier. diff --git a/src/doc/book/src/02-02-creating-a-new-project.md b/src/doc/book/src/02-02-creating-a-new-project.md new file mode 100644 index 00000000000..f457f609e56 --- /dev/null +++ b/src/doc/book/src/02-02-creating-a-new-project.md @@ -0,0 +1,111 @@ +## Creating a new project + +To start a new project with Cargo, use `cargo new`: + +```shell +$ cargo new hello_world --bin +``` + +We’re passing `--bin` because we’re making a binary program: if we +were making a library, we’d leave it off. This also initializes a new `git` +repository by default. If you don't want it to do that, pass `--vcs none`. + +Let’s check out what Cargo has generated for us: + +```shell +$ cd hello_world +$ tree . +. +├── Cargo.toml +└── src + └── main.rs + +1 directory, 2 files +``` + +If we had just used `cargo new hello_world` without the `--bin` flag, then +we would have a `lib.rs` instead of a `main.rs`. For now, however, this is all +we need to get started. First, let’s check out `Cargo.toml`: + +```toml +[package] +name = "hello_world" +version = "0.1.0" +authors = ["Your Name "] +``` + +This is called a **manifest**, and it contains all of the metadata that Cargo +needs to compile your project. + +Here’s what’s in `src/main.rs`: + +``` +fn main() { + println!("Hello, world!"); +} +``` + +Cargo generated a “hello world” for us. Let’s compile it: + +```shell +$ cargo build + Compiling hello_world v0.1.0 (file:///path/to/project/hello_world) +``` + +And then run it: + +```shell +$ ./target/debug/hello_world +Hello, world! +``` + +We can also use `cargo run` to compile and then run it, all in one step (you +won't see the `Compiling` line if you have not made any changes since you last +compiled): + +```shell +$ cargo run + Compiling hello_world v0.1.0 (file:///path/to/project/hello_world) + Running `target/debug/hello_world` +Hello, world! +``` + +You'll notice several new files and directories have been created: +```shell +$ tree . +. +├── Cargo.lock +├── Cargo.toml +├── src +│   └── main.rs +└── target + └── debug + ├── build + ├── deps + │   └── hello_world-2386c2fd0156916f + ├── examples + ├── hello_world + ├── hello_world.d + ├── incremental + └── native + +8 directories, 6 files +``` + +The `Cargo.lock` file contains information about our dependencies. Since we +don’t have any yet, it’s not very interesting. The `target` directory contains +all the build products, and, as can be seen, Cargo produces debug builds by +default. You can use `cargo build --release` to compile your files with +optimizations turned on: + +```shell +$ cargo build --release + Compiling hello_world v0.1.0 (file:///path/to/project/hello_world) +``` + +`cargo build --release` puts the resulting binary in `target/release` +instead of `target/debug`. + +Compiling in debug mode is the default for development -- compilation time is +shorter since the compiler doesn't do optimizations, but the code will run +slower. Release mode takes longer to compile, but the code will run faster. diff --git a/src/doc/book/src/02-03-working-on-an-existing-project.md b/src/doc/book/src/02-03-working-on-an-existing-project.md new file mode 100644 index 00000000000..25203988eb4 --- /dev/null +++ b/src/doc/book/src/02-03-working-on-an-existing-project.md @@ -0,0 +1,22 @@ +## Working on an existing Cargo project + +If you download an existing project that uses Cargo, it’s really easy +to get going. + +First, get the project from somewhere. In this example, we’ll use `rand` +cloned from its repository on GitHub: + +```shell +$ git clone https://github.com/rust-lang-nursery/rand.git +$ cd rand +``` + +To build, use `cargo build`: + +```shell +$ cargo build + Compiling rand v0.1.0 (file:///path/to/project/rand) +``` + +This will fetch all of the dependencies and then build them, along with the +project. diff --git a/src/doc/book/src/02-04-dependencies.md b/src/doc/book/src/02-04-dependencies.md new file mode 100644 index 00000000000..4f01b72e860 --- /dev/null +++ b/src/doc/book/src/02-04-dependencies.md @@ -0,0 +1,90 @@ +## Adding dependencies from crates.io + +[crates.io] is the Rust community's central repository that serves +as a location to discover and download packages. `cargo` is configured to use +it by default to find requested packages. + +To depend on a library hosted on [crates.io], add it to your `Cargo.toml`. + +[crates.io]: https://crates.io/ + +### Adding a dependency + +If your `Cargo.toml` doesn't already have a `[dependencies]` section, add that, +then list the crate name and version that you would like to use. This example +adds a dependency of the `time` crate: + +```toml +[dependencies] +time = "0.1.12" +``` + +The version string is a [semver] version requirement. The [specifying +dependencies](03-01-specifying-dependencies.html) docs have more information about +the options you have here. + +[semver]: https://github.com/steveklabnik/semver#requirements + +If we also wanted to add a dependency on the `regex` crate, we would not need +to add `[dependencies]` for each crate listed. Here's what your whole +`Cargo.toml` file would look like with dependencies on the `time` and `regex` +crates: + +```toml +[package] +name = "hello_world" +version = "0.1.0" +authors = ["Your Name "] + +[dependencies] +time = "0.1.12" +regex = "0.1.41" +``` + +Re-run `cargo build`, and Cargo will fetch the new dependencies and all of +their dependencies, compile them all, and update the `Cargo.lock`: + +```shell +$ cargo build + Updating registry `https://github.com/rust-lang/crates.io-index` + Downloading memchr v0.1.5 + Downloading libc v0.1.10 + Downloading regex-syntax v0.2.1 + Downloading memchr v0.1.5 + Downloading aho-corasick v0.3.0 + Downloading regex v0.1.41 + Compiling memchr v0.1.5 + Compiling libc v0.1.10 + Compiling regex-syntax v0.2.1 + Compiling memchr v0.1.5 + Compiling aho-corasick v0.3.0 + Compiling regex v0.1.41 + Compiling hello_world v0.1.0 (file:///path/to/project/hello_world) +``` + +Our `Cargo.lock` contains the exact information about which revision of all of +these dependencies we used. + +Now, if `regex` gets updated, we will still build with the same revision until +we choose to `cargo update`. + +You can now use the `regex` library using `extern crate` in `main.rs`. + +``` +extern crate regex; + +use regex::Regex; + +fn main() { + let re = Regex::new(r"^\d{4}-\d{2}-\d{2}$").unwrap(); + println!("Did our date match? {}", re.is_match("2014-01-01")); +} +``` + +Running it will show: + +```shell +$ cargo run + Running `target/hello_world` +Did our date match? true +``` diff --git a/src/doc/book/src/02-05-project-layout.md b/src/doc/book/src/02-05-project-layout.md new file mode 100644 index 00000000000..18657225190 --- /dev/null +++ b/src/doc/book/src/02-05-project-layout.md @@ -0,0 +1,136 @@ +## Project layout + +Cargo uses conventions for file placement to make it easy to dive into a new +Cargo project: + +```shell +. +├── Cargo.lock +├── Cargo.toml +├── benches +│   └── large-input.rs +├── examples +│   └── simple.rs +├── src +│   ├── bin +│   │   └── another_executable.rs +│   ├── lib.rs +│   └── main.rs +└── tests + └── some-integration-tests.rs +``` + +* `Cargo.toml` and `Cargo.lock` are stored in the root of your project. +* Source code goes in the `src` directory. +* The default library file is `src/lib.rs`. +* The default executable file is `src/main.rs`. +* Other executables can be placed in `src/bin/*.rs`. +* Integration tests go in the `tests` directory (unit tests go in each file they're testing). +* Examples go in the `examples` directory. +* Benchmarks go in the `benches` directory. + +These are explained in more detail in the [manifest +description](03-02-manifest.html#the-project-layout). + +## Cargo.toml vs Cargo.lock + +`Cargo.toml` and `Cargo.lock` serve two different purposes. Before we talk +about them, here’s a summary: + +* `Cargo.toml` is about describing your dependencies in a broad sense, and is written by you. +* `Cargo.lock` contains exact information about your dependencies. It is maintained by Cargo and should not be manually edited. + +If you’re building a library that other projects will depend on, put +`Cargo.lock` in your `.gitignore`. If you’re building an executable like a +command-line tool or an application, check `Cargo.lock` into `git`. If you're +curious about why that is, see ["Why do binaries have `Cargo.lock` in version +control, but not libraries?" in the +FAQ](faq.html#why-do-binaries-have-cargolock-in-version-control-but-not-libraries). + +Let’s dig in a little bit more. + +`Cargo.toml` is a **manifest** file in which we can specify a bunch of +different metadata about our project. For example, we can say that we depend +on another project: + +```toml +[package] +name = "hello_world" +version = "0.1.0" +authors = ["Your Name "] + +[dependencies] +rand = { git = "https://github.com/rust-lang-nursery/rand.git" } +``` + +This project has a single dependency, on the `rand` library. We’ve stated in +this case that we’re relying on a particular Git repository that lives on +GitHub. Since we haven’t specified any other information, Cargo assumes that +we intend to use the latest commit on the `master` branch to build our project. + +Sound good? Well, there’s one problem: If you build this project today, and +then you send a copy to me, and I build this project tomorrow, something bad +could happen. There could be more commits to `rand` in the meantime, and my +build would include new commits while yours would not. Therefore, we would +get different builds. This would be bad because we want reproducible builds. + +We could fix this problem by putting a `rev` line in our `Cargo.toml`: + +```toml +[dependencies] +rand = { git = "https://github.com/rust-lang-nursery/rand.git", rev = "9f35b8e" } +``` + +Now our builds will be the same. But there’s a big drawback: now we have to +manually think about SHA-1s every time we want to update our library. This is +both tedious and error prone. + +Enter the `Cargo.lock`. Because of its existence, we don’t need to manually +keep track of the exact revisions: Cargo will do it for us. When we have a +manifest like this: + +```toml +[package] +name = "hello_world" +version = "0.1.0" +authors = ["Your Name "] + +[dependencies] +rand = { git = "https://github.com/rust-lang-nursery/rand.git" } +``` + +Cargo will take the latest commit and write that information out into our +`Cargo.lock` when we build for the first time. That file will look like this: + +```toml +[root] +name = "hello_world" +version = "0.1.0" +dependencies = [ + "rand 0.1.0 (git+https://github.com/rust-lang-nursery/rand.git#9f35b8e439eeedd60b9414c58f389bdc6a3284f9)", +] + +[[package]] +name = "rand" +version = "0.1.0" +source = "git+https://github.com/rust-lang-nursery/rand.git#9f35b8e439eeedd60b9414c58f389bdc6a3284f9" + +``` + +You can see that there’s a lot more information here, including the exact +revision we used to build. Now when you give your project to someone else, +they’ll use the exact same SHA, even though we didn’t specify it in our +`Cargo.toml`. + +When we’re ready to opt in to a new version of the library, Cargo can +re-calculate the dependencies and update things for us: + +```shell +$ cargo update # updates all dependencies +$ cargo update -p rand # updates just “rand” +``` + +This will write out a new `Cargo.lock` with the new version information. Note +that the argument to `cargo update` is actually a +[Package ID Specification](03-07-pkgid-spec.html) and `rand` is just a short +specification. diff --git a/src/doc/book/src/02-06-tests.md b/src/doc/book/src/02-06-tests.md new file mode 100644 index 00000000000..db5ec20aff0 --- /dev/null +++ b/src/doc/book/src/02-06-tests.md @@ -0,0 +1,39 @@ +## Tests + +Cargo can run your tests with the `cargo test` command. Cargo looks for tests +to run in two places: in each of your `src` files and any tests in `tests/`. +Tests in your `src` files should be unit tests, and tests in `tests/` should be +integration-style tests. As such, you’ll need to import your crates into +the files in `tests`. + +Here's an example of running `cargo test` in our project, which currently has +no tests: + +```shell +$ cargo test + Compiling rand v0.1.0 (https://github.com/rust-lang-nursery/rand.git#9f35b8e) + Compiling hello_world v0.1.0 (file:///path/to/project/hello_world) + Running target/test/hello_world-9c2b65bbb79eabce + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured +``` + +If our project had tests, we would see more output with the correct number of +tests. + +You can also run a specific test by passing a filter: + +```shell +$ cargo test foo +``` + +This will run any test with `foo` in its name. + +`cargo test` runs additional checks as well. For example, it will compile any +examples you’ve included and will also test the examples in your +documentation. Please see the [testing guide][testing] in the Rust +documentation for more details. + +[testing]: https://doc.rust-lang.org/book/testing.html diff --git a/src/doc/book/src/02-07-continuous-integration.md b/src/doc/book/src/02-07-continuous-integration.md new file mode 100644 index 00000000000..cc10cfe56ed --- /dev/null +++ b/src/doc/book/src/02-07-continuous-integration.md @@ -0,0 +1,21 @@ +## Continuous integration + +### Travis CI + +To test your project on Travis CI, here is a sample `.travis.yml` file: + +``` +language: rust +rust: + - stable + - beta + - nightly +matrix: + allow_failures: + - rust: nightly +``` + +This will test all three release channels, but any breakage in nightly +will not fail your overall build. Please see the [Travis CI Rust +documentation](https://docs.travis-ci.com/user/languages/rust/) for more +information. diff --git a/src/doc/book/src/03-01-specifying-dependencies.md b/src/doc/book/src/03-01-specifying-dependencies.md new file mode 100644 index 00000000000..844b9155d9b --- /dev/null +++ b/src/doc/book/src/03-01-specifying-dependencies.md @@ -0,0 +1,526 @@ +## Specifying Dependencies + +Your crates can depend on other libraries from [crates.io], `git` repositories, or +subdirectories on your local file system. You can also temporarily override the +location of a dependency— for example, to be able to test out a bug fix in the +dependency that you are working on locally. You can have different +dependencies for different platforms, and dependencies that are only used during +development. Let's take a look at how to do each of these. + +### Specifying dependencies from crates.io + +Cargo is configured to look for dependencies on [crates.io] by default. Only +the name and a version string are required in this case. In [the cargo +guide](guide.html), we specified a dependency on the `time` crate: + +```toml +[dependencies] +time = "0.1.12" +``` + +The string `"0.1.12"` is a [semver] version requirement. Since this +string does not have any operators in it, it is interpreted the same way as +if we had specified `"^0.1.12"`, which is called a caret requirement. + +[semver]: https://github.com/steveklabnik/semver#requirements + +### Caret requirements + +**Caret requirements** allow SemVer compatible updates to a specified version. +An update is allowed if the new version number does not modify the left-most +non-zero digit in the major, minor, patch grouping. In this case, if we ran +`cargo update -p time`, cargo would update us to version `0.1.13` if it was +available, but would not update us to `0.2.0`. If instead we had specified the +version string as `^1.0`, cargo would update to `1.1` but not `2.0`. `0.0.x` is +not considered compatible with any other version. + +Here are some more examples of caret requirements and the versions that would +be allowed with them: + +```notrust +^1.2.3 := >=1.2.3 <2.0.0 +^1.2 := >=1.2.0 <2.0.0 +^1 := >=1.0.0 <2.0.0 +^0.2.3 := >=0.2.3 <0.3.0 +^0.0.3 := >=0.0.3 <0.0.4 +^0.0 := >=0.0.0 <0.1.0 +^0 := >=0.0.0 <1.0.0 +``` + +While SemVer says that there is no compatibility before 1.0.0, many programmers +treat a `0.x.y` release in the same way as a `1.x.y` release: that is, `y` is +incremented for bugfixes, and `x` is incremented for new features. As such, +Cargo considers a `0.x.y` and `0.x.z` version, where `z > y`, to be compatible. + +### Tilde requirements + +**Tilde requirements** specify a minimal version with some ability to update. +If you specify a major, minor, and patch version or only a major and minor +version, only patch-level changes are allowed. If you only specify a major +version, then minor- and patch-level changes are allowed. + +`~1.2.3` is an example of a tilde requirement. + +```notrust +~1.2.3 := >=1.2.3 <1.3.0 +~1.2 := >=1.2.0 <1.3.0 +~1 := >=1.0.0 <2.0.0 +``` + +### Wildcard requirements + +**Wildcard requirements** allow for any version where the wildcard is +positioned. + +`*`, `1.*` and `1.2.*` are examples of wildcard requirements. + +```notrust +* := >=0.0.0 +1.* := >=1.0.0 <2.0.0 +1.2.* := >=1.2.0 <1.3.0 +``` + +### Inequality requirements + +**Inequality requirements** allow manually specifying a version range or an +exact version to depend on. + +Here are some examples of inequality requirements: + +```notrust +>= 1.2.0 +> 1 +< 2 += 1.2.3 +``` + +### Multiple requirements + +Multiple version requirements can also be separated with a comma, e.g. `>= 1.2, +< 1.5`. + +### Specifying dependencies from `git` repositories + +To depend on a library located in a `git` repository, the minimum information +you need to specify is the location of the repository with the `git` key: + +```toml +[dependencies] +rand = { git = "https://github.com/rust-lang-nursery/rand" } +``` + +Cargo will fetch the `git` repository at this location then look for a +`Cargo.toml` for the requested crate anywhere inside the `git` repository +(not necessarily at the root). + +Since we haven’t specified any other information, Cargo assumes that +we intend to use the latest commit on the `master` branch to build our project. +You can combine the `git` key with the `rev`, `tag`, or `branch` keys to +specify something else. Here's an example of specifying that you want to use +the latest commit on a branch named `next`: + +```toml +[dependencies] +rand = { git = "https://github.com/rust-lang-nursery/rand", branch = "next" } +``` + +### Specifying path dependencies + +Over time, our `hello_world` project from [the guide](guide.html) has grown +significantly in size! It’s gotten to the point that we probably want to +split out a separate crate for others to use. To do this Cargo supports +**path dependencies** which are typically sub-crates that live within one +repository. Let’s start off by making a new crate inside of our `hello_world` +project: + +```shell +# inside of hello_world/ +$ cargo new hello_utils +``` + +This will create a new folder `hello_utils` inside of which a `Cargo.toml` and +`src` folder are ready to be configured. In order to tell Cargo about this, open +up `hello_world/Cargo.toml` and add `hello_utils` to your dependencies: + +```toml +[dependencies] +hello_utils = { path = "hello_utils" } +``` + +This tells Cargo that we depend on a crate called `hello_utils` which is found +in the `hello_utils` folder (relative to the `Cargo.toml` it’s written in). + +And that’s it! The next `cargo build` will automatically build `hello_utils` and +all of its own dependencies, and others can also start using the crate as well. +However, crates that use dependencies specified with only a path are not +permitted on [crates.io]. If we wanted to publish our `hello_world` crate, we +would need to publish a version of `hello_utils` to [crates.io](https://crates.io) +(or specify a `git` repository location) and specify its version in +the dependencies line as well: + +```toml +[dependencies] +hello_utils = { path = "hello_utils", version = "0.1.0" } +``` + +### Overriding dependencies + +There are a number of methods in Cargo to support overriding dependencies and +otherwise controlling the dependency graph. These options are typically, though, +only available at the workspace level and aren't propagated through +dependencies. In other words, "applications" have the ability to override +dependencies but "libraries" do not. + +The desire to override a dependency or otherwise alter some dependencies can +arise through a number of scenarios. Most of them, however, boil down to the +ability to to work with a crate before it's been published to crates.io. For +example: + +* A crate you're working on is also used in a much larger application you're + working on, and you'd like to test a bug fix to the library inside of the + larger application. +* An upstream crate you don't work on has a new feature or a bug fix on the + master branch of its git repository which you'd like to test out. +* You're about to publish a new major version of your crate, but you'd like to + do integration testing across an entire project to ensure the new major + version works. +* You've submitted a fix to an upstream crate for a bug you found, but you'd + like to immediately have your application start depending on the fixed version + of the crate to avoid blocking on the bug fix getting merged. + +These scenarios are currently all solved with the [`[patch]` manifest +section][patch-section]. Note that the `[patch]` feature is not yet currently +stable and will be released on 2017-08-31. Historically some of these scenarios +have been solved with [the `[replace]` section][replace-section], but we'll +document the `[patch]` section here. + +[patch-section]: 03-02-manifest.html#the-patch-section +[replace-section]: 03-02-manifest.html#the-replace-section + +### Testing a bugfix + +Let's say you're working with the [`uuid`] crate but while you're working on it +you discover a bug. You are, however, quite enterprising so you decide to also +try out to fix the bug! Originally your manifest will look like: + +[`uuid`](https://crates.io/crates/uuid) + +```toml +[package] +name = "my-library" +version = "0.1.0" +authors = ["..."] + +[dependencies] +uuid = "1.0" +``` + +First thing we'll do is to clone the [`uuid` repository][uuid-repository] +locally via: + +```shell +$ git clone https://github.com/rust-lang-nursery/uuid +``` + +Next we'll edit the manifest of `my-library` to contain: + +```toml +[patch.crates-io] +uuid = { path = "../path/to/uuid" } +``` + +Here we declare that we're *patching* the source `crates-io` with a new +dependency. This will effectively add the local checked out version of `uuid` to +the crates.io registry for our local project. + +Next up we need to ensure that our lock file is updated to use this new version +of `uuid` so our project uses the locally checked out copy instead of one from +crates.io. The way `[patch]` works is that it'll load the dependency at +`../path/to/uuid` and then whenever crates.io is queried for versions of `uuid` +it'll *also* return the local version. + +This means that the version number of the local checkout is significant and will +affect whether the patch is used. Our manifest declared `uuid = "1.0"` which +means we'll only resolve to `>= 1.0.0, < 2.0.0`, and Cargo's greedy resolution +algorithm also means that we'll resolve to the maximum version within that +range. Typically this doesn't matter as the version of the git repository will +already be greater or match the maximum version published on crates.io, but it's +important to keep this in mind! + +In any case, typically all you need to do now is: + +```shell +$ cargo build + Compiling uuid v1.0.0 (file://.../uuid) + Compiling my-library v0.1.0 (file://.../my-library) + Finished dev [unoptimized + debuginfo] target(s) in 0.32 secs +``` + +And that's it! You're now building with the local version of `uuid` (note the +`file://` in the build output). If you don't see the `file://` version getting +built then you may need to run `cargo update -p uuid --precise $version` where +`$version` is the version of the locally checked out copy of `uuid`. + +Once you've fixed the bug you originally found the next thing you'll want to do +is to likely submit that as a pull request to the `uuid` crate itself. Once +you've done this then you can also update the `[patch]` section. The listing +inside of `[patch]` is just like the `[dependencies]` section, so once your pull +request is merged you could change your `path` dependency to: + +```toml +[patch.crates-io] +uuid = { git = 'https://github.com/rust-lang-nursery/uuid' } +``` + +[uuid-repository]: https://github.com/rust-lang-nursery/uuid + +### Working with an unpublished minor version + +Let's now shift gears a bit from bug fixes to adding features. While working on +`my-library` you discover that a whole new feature is needed in the `uuid` +crate. You've implemented this feature, tested it locally above with `[patch]`, +and submitted a pull request. Let's go over how you continue to use and test it +before it's actually published. + +Let's also say that the current version of `uuid` on crates.io is `1.0.0`, but +since then the master branch of the git repository has updated to `1.0.1`. This +branch includes your new feature you submitted previously. To use this +repository we'll edit our `Cargo.toml` to look like + +```toml +[package] +name = "my-library" +version = "0.1.0" +authors = ["..."] + +[dependencies] +uuid = "1.0.1" + +[patch.crates-io] +uuid = { git = 'https://github.com/rust-lang-nursery/uuid' } +``` + +Note that our local dependency on `uuid` has been updated to `1.0.1` as it's +what we'll actually require once the crate is published. This version doesn't +exist on crates.io, though, so we provide it with the `[patch]` section of the +manifest. + +Now when our library is built it'll fetch `uuid` from the git repository and +resolve to 1.0.1 inside the repository instead of trying to download a version +from crates.io. Once 1.0.1 is published on crates.io the `[patch]` section can +be deleted. + +It's also worth nothing that `[patch]` applies *transitively*. Let's say you use +`my-library` in a larger project, such as: + +```toml +[package] +name = "my-binary" +version = "0.1.0" +authors = ["..."] + +[dependencies] +my-library = { git = 'https://example.com/git/my-library' } +uuid = "1.0" + +[patch.crates-io] +uuid = { git = 'https://github.com/rust-lang-nursery/uuid' } +``` + +Remember that `[patch]` is only applicable at the *top level* so we consumers of +`my-library` have to repeat the `[patch]` section if necessary. Here, though, +the new `uuid` crate applies to *both* our dependency on `uuid` and the +`my-library -> uuid` dependency. The `uuid` crate will be resolved to one +version for this entire crate graph, 1.0.1, and it'll be pulled from the git +repository. + +### Prepublishing a breaking change + +As a final scenario, let's take a look at working with a new major version of a +crate, typically accompanied with breaking changes. Sticking with our previous +crates, this means that we're going to be creating version 2.0.0 of the `uuid` +crate. After we've submitted all changes upstream we can update our manifest for +`my-library` to look like: + +```toml +[dependencies] +uuid = "2.0" + +[patch.crates-io] +uuid = { git = "https://github.com/rust-lang-nursery/uuid", branch = "2.0.0" } +``` + +And that's it! Like with the previous example the 2.0.0 version doesn't actually +exist on crates.io but we can still put it in through a git dependency through +the usage of the `[patch]` section. As a thought exercise let's take another +look at the `my-binary` manifest from above again as well: + +```toml +[package] +name = "my-binary" +version = "0.1.0" +authors = ["..."] + +[dependencies] +my-library = { git = 'https://example.com/git/my-library' } +uuid = "1.0" + +[patch.crates-io] +uuid = { git = 'https://github.com/rust-lang-nursery/uuid', version = '2.0.0' } +``` + +Note that this will actually resolve to two versions of the `uuid` crate. The +`my-binary` crate will continue to use the 1.x.y series of the `uuid` crate but +the `my-library` crate will use the 2.0.0 version of `uuid`. This will allow you +to gradually roll out breaking changes to a crate through a dependency graph +without being force to update everything all at once. + +### Overriding with local dependencies + +Sometimes you're only temporarily working on a crate and you don't want to have +to modify `Cargo.toml` like with the `[patch]` section above. For this use +case Cargo offers a much more limited version of overrides called **path +overrides**. + +Path overrides are specified through `.cargo/config` instead of `Cargo.toml`, +and you can find [more documentation about this configuration][config-docs]. +Inside of `.cargo/config` you'll specify a key called `paths`: + +[config-docs]: config.html + +```toml +paths = ["/path/to/uuid"] +``` + +This array should be filled with directories that contain a `Cargo.toml`. In +this instance, we’re just adding `uuid`, so it will be the only one that’s +overridden. This path can be either absolute or relative to the directory that +contains the `.cargo` folder. + +Path overrides are more restricted than the `[patch]` section, however, in +that they cannot change the structure of the dependency graph. When a +path replacement is used then the previous set of dependencies +must all match exactly to the new `Cargo.toml` specification. For example this +means that path overrides cannot be used to test out adding a dependency to a +crate, instead `[patch]` must be used in that situation. As a result usage of a +path override is typically isolated to quick bug fixes rather than larger +changes. + +Note: using a local configuration to override paths will only work for crates +that have been published to [crates.io]. You cannot use this feature to tell +Cargo how to find local unpublished crates. + +### Platform specific dependencies + + +Platform-specific dependencies take the same format, but are listed under a +`target` section. Normally Rust-like `#[cfg]` syntax will be used to define +these sections: + +```toml +[target.'cfg(windows)'.dependencies] +winhttp = "0.4.0" + +[target.'cfg(unix)'.dependencies] +openssl = "1.0.1" + +[target.'cfg(target_arch = "x86")'.dependencies] +native = { path = "native/i686" } + +[target.'cfg(target_arch = "x86_64")'.dependencies] +native = { path = "native/x86_64" } +``` + +Like with Rust, the syntax here supports the `not`, `any`, and `all` operators +to combine various cfg name/value pairs. Note that the `cfg` syntax has only +been available since Cargo 0.9.0 (Rust 1.8.0). + +In addition to `#[cfg]` syntax, Cargo also supports listing out the full target +the dependencies would apply to: + +```toml +[target.x86_64-pc-windows-gnu.dependencies] +winhttp = "0.4.0" + +[target.i686-unknown-linux-gnu.dependencies] +openssl = "1.0.1" +``` + +If you’re using a custom target specification, quote the full path and file +name: + +```toml +[target."x86_64/windows.json".dependencies] +winhttp = "0.4.0" + +[target."i686/linux.json".dependencies] +openssl = "1.0.1" +native = { path = "native/i686" } + +[target."x86_64/linux.json".dependencies] +openssl = "1.0.1" +native = { path = "native/x86_64" } +``` + +### Development dependencies + +You can add a `[dev-dependencies]` section to your `Cargo.toml` whose format +is equivalent to `[dependencies]`: + +```toml +[dev-dependencies] +tempdir = "0.3" +``` + +Dev-dependencies are not used when compiling +a package for building, but are used for compiling tests, examples, and +benchmarks. + +These dependencies are *not* propagated to other packages which depend on this +package. + +You can also have target-specific development dependencies by using +`dev-dependencies` in the target section header instead of `dependencies`. For +example: + +```toml +[target.'cfg(unix)'.dev-dependencies] +mio = "0.0.1" +``` + +[crates.io]: https://crates.io/ + +### Build dependencies + +You can depend on other Cargo-based crates for use in your build scripts. +Dependencies are declared through the `build-dependencies` section of the +manifest: + +```toml +[build-dependencies] +gcc = "0.3" +``` + +The build script **does not** have access to the dependencies listed +in the `dependencies` or `dev-dependencies` section. Build +dependencies will likewise not be available to the package itself +unless listed under the `dependencies` section as well. A package +itself and its build script are built separately, so their +dependencies need not coincide. Cargo is kept simpler and cleaner by +using independent dependencies for independent purposes. + +### Choosing features + +If a package you depend on offers conditional features, you can +specify which to use: + +```toml +[dependencies.awesome] +version = "1.3.5" +default-features = false # do not include the default features, and optionally + # cherry-pick individual features +features = ["secure-password", "civet"] +``` + +More information about features can be found in the +[manifest documentation](03-02-manifest.html#the-features-section). diff --git a/src/doc/book/src/03-02-manifest.md b/src/doc/book/src/03-02-manifest.md new file mode 100644 index 00000000000..6068bb5a534 --- /dev/null +++ b/src/doc/book/src/03-02-manifest.md @@ -0,0 +1,725 @@ +## The Manifest Format + +### The `[package]` section + +The first section in a `Cargo.toml` is `[package]`. + +```toml +[package] +name = "hello_world" # the name of the package +version = "0.1.0" # the current version, obeying semver +authors = ["you@example.com"] +``` + +All three of these fields are mandatory. + +#### The `version` field + +Cargo bakes in the concept of [Semantic +Versioning](http://semver.org/), so make sure you follow some basic rules: + +* Before you reach 1.0.0, anything goes, but if you make breaking changes, + increment the minor version. In Rust, breaking changes include adding fields to + structs or variants to enums. +* After 1.0.0, only make breaking changes when you increment the major version. + Don’t break the build. +* After 1.0.0, don’t add any new public API (no new `pub` anything) in tiny + versions. Always increment the minor version if you add any new `pub` structs, + traits, fields, types, functions, methods or anything else. +* Use version numbers with three numeric parts such as 1.0.0 rather than 1.0. + +#### The `build` field (optional) + +This field specifies a file in the repository which is a [build script][1] for +building native code. More information can be found in the build script +[guide][1]. + +[1]: 03-05-build-scripts.html + +```toml +[package] +# ... +build = "build.rs" +``` + +#### The `documentation` field (optional) + +This field specifies a URL to a website hosting the crate's documentation. +If no URL is specified in the manifest file, [crates.io][cratesio] will +automatically link your crate to the corresponding [docs.rs][docsrs] page. + +Documentation links from specific hosts are blacklisted. Hosts are added +to the blacklist if they are known to not be hosting documentation and are +possibly of malicious intent e.g. ad tracking networks. URLs from the +following hosts are blacklisted: +- rust-ci.org + +Documentation URLs from blacklisted hosts will not appear on crates.io, and +may be replaced by docs.rs links. + +[docsrs]: https://docs.rs/ +[cratesio]: https://crates.io/ + +#### The `exclude` and `include` fields (optional) + +You can explicitly specify to Cargo that a set of [globs][globs] should be +ignored or included for the purposes of packaging and rebuilding a package. The +globs specified in the `exclude` field identify a set of files that are not +included when a package is published as well as ignored for the purposes of +detecting when to rebuild a package, and the globs in `include` specify files +that are explicitly included. + +If a VCS is being used for a package, the `exclude` field will be seeded with +the VCS’ ignore settings (`.gitignore` for git for example). + +```toml +[package] +# ... +exclude = ["build/**/*.o", "doc/**/*.html"] +``` + +```toml +[package] +# ... +include = ["src/**/*", "Cargo.toml"] +``` + +The options are mutually exclusive: setting `include` will override an +`exclude`. Note that `include` must be an exhaustive list of files as otherwise +necessary source files may not be included. + +[globs]: http://doc.rust-lang.org/glob/glob/struct.Pattern.html + +#### Migrating to `gitignore`-like pattern matching + +The current interpretation of these configs is based on UNIX Globs, as +implemented in the [`glob` crate](https://crates.io/crates/glob). We want +Cargo's `include` and `exclude` configs to work as similar to `gitignore` as +possible. [The `gitignore` specification](https://git-scm.com/docs/gitignore) is +also based on Globs, but has a bunch of additional features that enable easier +pattern writing and more control. Therefore, we are migrating the interpretation +for the rules of these configs to use the [`ignore` +crate](https://crates.io/crates/ignore), and treat them each rule as a single +line in a `gitignore` file. See [the tracking +issue](https://github.com/rust-lang/cargo/issues/4268) for more details on the +migration. + +#### The `publish` field (optional) + +The `publish` field can be used to prevent a package from being published to a +repository by mistake. + +```toml +[package] +# ... +publish = false +``` + +#### The `workspace` field (optional) + +The `workspace` field can be used to configure the workspace that this package +will be a member of. If not specified this will be inferred as the first +Cargo.toml with `[workspace]` upwards in the filesystem. + +```toml +[package] +# ... +workspace = "path/to/root" +``` + +For more information, see the documentation for the workspace table below. + +#### Package metadata + +There are a number of optional metadata fields also accepted under the +`[package]` section: + +```toml +[package] +# ... + +# A short blurb about the package. This is not rendered in any format when +# uploaded to crates.io (aka this is not markdown). +description = "..." + +# These URLs point to more information about the repository. These are +# intended to be webviews of the relevant data, not necessarily compatible +# with VCS tools and the like. +documentation = "..." +homepage = "..." +repository = "..." + +# This points to a file in the repository (relative to this `Cargo.toml`). The +# contents of this file are stored and indexed in the registry. +readme = "..." + +# This is a list of up to five keywords that describe this crate. Keywords +# are searchable on crates.io, and you may choose any words that would +# help someone find this crate. +keywords = ["...", "..."] + +# This is a list of up to five categories where this crate would fit. +# Categories are a fixed list available at crates.io/category_slugs, and +# they must match exactly. +categories = ["...", "..."] + +# This is a string description of the license for this package. Currently +# crates.io will validate the license provided against a whitelist of known +# license identifiers from http://spdx.org/licenses/. Multiple licenses can be +# separated with a `/`. +license = "..." + +# If a project is using a nonstandard license, then this key may be specified in +# lieu of the above key and must point to a file relative to this manifest +# (similar to the readme key). +license-file = "..." + +# Optional specification of badges to be displayed on crates.io. The badges +# currently available are Travis CI, Appveyor, and GitLab latest build status, +# specified using the following parameters: +[badges] +# Travis CI: `repository` in format "/" is required. +# `branch` is optional; default is `master` +travis-ci = { repository = "...", branch = "master" } +# Appveyor: `repository` is required. `branch` is optional; default is `master` +# `service` is optional; valid values are `github` (default), `bitbucket`, and +# `gitlab`. +appveyor = { repository = "...", branch = "master", service = "github" } +# GitLab: `repository` is required. `branch` is optional; default is `master` +gitlab = { repository = "...", branch = "master" } +# Circle CI: `repository` is required. `branch` is optional; default is `master` +circle-ci = { repository = "...", branch = "master" } +# Is it maintained resolution time: `repository` is required. +is-it-maintained-issue-resolution = { repository = "..." } +# Is it maintained percentage of open issues: `repository` is required. +is-it-maintained-open-issues = { repository = "..." } +# Codecov: `repository` is required. `branch` is optional; default is `master` +# `service` is optional; valid values are `github` (default), `bitbucket`, and +# `gitlab`. +codecov = { repository = "...", branch = "master", service = "github" } +# Coveralls: `repository` is required. `branch` is optional; default is `master` +# `service` is optional; valid values are `github` (default) and `bitbucket`. +coveralls = { repository = "...", branch = "master", service = "github" } +``` + +The [crates.io](https://crates.io) registry will render the description, display +the license, link to the three URLs and categorize by the keywords. These keys +provide useful information to users of the registry and also influence the +search ranking of a crate. It is highly discouraged to omit everything in a +published crate. + +#### The `metadata` table (optional) + +Cargo by default will warn about unused keys in `Cargo.toml` to assist in +detecting typos and such. The `package.metadata` table, however, is completely +ignored by Cargo and will not be warned about. This section can be used for +tools which would like to store project configuration in `Cargo.toml`. For +example: + +```toml +[package] +name = "..." +# ... + +# Metadata used when generating an Android APK, for example. +[package.metadata.android] +package-name = "my-awesome-android-app" +assets = "path/to/static" +``` + +### Dependency sections + +See the [specifying dependencies page](03-01-specifying-dependencies.html) for +information on the `[dependencies]`, `[dev-dependencies]`, +`[build-dependencies]`, and target-specific `[target.*.dependencies]` sections. + +### The `[profile.*]` sections + +Cargo supports custom configuration of how rustc is invoked through profiles at +the top level. Any manifest may declare a profile, but only the top level +project’s profiles are actually read. All dependencies’ profiles will be +overridden. This is done so the top-level project has control over how its +dependencies are compiled. + +There are five currently supported profile names, all of which have the same +configuration available to them. Listed below is the configuration available, +along with the defaults for each profile. + +```toml +# The development profile, used for `cargo build`. +[profile.dev] +opt-level = 0 # controls the `--opt-level` the compiler builds with. + # 0-1 is good for debugging. 2 is well-optimized. Max is 3. +debug = true # include debug information (debug symbols). Equivalent to + # `-C debuginfo=2` compiler flag. +rpath = false # controls whether compiler should set loader paths. + # If true, passes `-C rpath` flag to the compiler. +lto = false # Link Time Optimization usually reduces size of binaries + # and static libraries. Increases compilation time. + # If true, passes `-C lto` flag to the compiler. +debug-assertions = true # controls whether debug assertions are enabled + # (e.g. debug_assert!() and arithmetic overflow checks) +codegen-units = 1 # if > 1 enables parallel code generation which improves + # compile times, but prevents some optimizations. + # Passes `-C codegen-units`. Ignored when `lto = true`. +panic = 'unwind' # panic strategy (`-C panic=...`), can also be 'abort' + +# The release profile, used for `cargo build --release`. +[profile.release] +opt-level = 3 +debug = false +rpath = false +lto = false +debug-assertions = false +codegen-units = 1 +panic = 'unwind' + +# The testing profile, used for `cargo test`. +[profile.test] +opt-level = 0 +debug = 2 +rpath = false +lto = false +debug-assertions = true +codegen-units = 1 +panic = 'unwind' + +# The benchmarking profile, used for `cargo bench`. +[profile.bench] +opt-level = 3 +debug = false +rpath = false +lto = false +debug-assertions = false +codegen-units = 1 +panic = 'unwind' + +# The documentation profile, used for `cargo doc`. +[profile.doc] +opt-level = 0 +debug = 2 +rpath = false +lto = false +debug-assertions = true +codegen-units = 1 +panic = 'unwind' +``` + +### The `[features]` section + +Cargo supports features to allow expression of: + +* conditional compilation options (usable through `cfg` attributes); +* optional dependencies, which enhance a package, but are not required; and +* clusters of optional dependencies, such as `postgres`, that would include the + `postgres` package, the `postgres-macros` package, and possibly other packages + (such as development-time mocking libraries, debugging tools, etc.). + +A feature of a package is either an optional dependency, or a set of other +features. The format for specifying features is: + +```toml +[package] +name = "awesome" + +[features] +# The default set of optional packages. Most people will want to use these +# packages, but they are strictly optional. Note that `session` is not a package +# but rather another feature listed in this manifest. +default = ["jquery", "uglifier", "session"] + +# A feature with no dependencies is used mainly for conditional compilation, +# like `#[cfg(feature = "go-faster")]`. +go-faster = [] + +# The `secure-password` feature depends on the bcrypt package. This aliasing +# will allow people to talk about the feature in a higher-level way and allow +# this package to add more requirements to the feature in the future. +secure-password = ["bcrypt"] + +# Features can be used to reexport features of other packages. The `session` +# feature of package `awesome` will ensure that the `session` feature of the +# package `cookie` is also enabled. +session = ["cookie/session"] + +[dependencies] +# These packages are mandatory and form the core of this package’s distribution. +cookie = "1.2.0" +oauth = "1.1.0" +route-recognizer = "=2.1.0" + +# A list of all of the optional dependencies, some of which are included in the +# above `features`. They can be opted into by apps. +jquery = { version = "1.0.2", optional = true } +uglifier = { version = "1.5.3", optional = true } +bcrypt = { version = "*", optional = true } +civet = { version = "*", optional = true } +``` + +To use the package `awesome`: + +```toml +[dependencies.awesome] +version = "1.3.5" +default-features = false # do not include the default features, and optionally + # cherry-pick individual features +features = ["secure-password", "civet"] +``` + +#### Rules + +The usage of features is subject to a few rules: + +* Feature names must not conflict with other package names in the manifest. This + is because they are opted into via `features = [...]`, which only has a single + namespace. +* With the exception of the `default` feature, all features are opt-in. To opt + out of the default feature, use `default-features = false` and cherry-pick + individual features. +* Feature groups are not allowed to cyclically depend on one another. +* Dev-dependencies cannot be optional. +* Features groups can only reference optional dependencies. +* When a feature is selected, Cargo will call `rustc` with `--cfg + feature="${feature_name}"`. If a feature group is included, it and all of its + individual features will be included. This can be tested in code via + `#[cfg(feature = "foo")]`. + +Note that it is explicitly allowed for features to not actually activate any +optional dependencies. This allows packages to internally enable/disable +features without requiring a new dependency. + +#### Usage in end products + +One major use-case for this feature is specifying optional features in +end-products. For example, the Servo project may want to include optional +features that people can enable or disable when they build it. + +In that case, Servo will describe features in its `Cargo.toml` and they can be +enabled using command-line flags: + +``` +$ cargo build --release --features "shumway pdf" +``` + +Default features could be excluded using `--no-default-features`. + +#### Usage in packages + +In most cases, the concept of *optional dependency* in a library is best +expressed as a separate package that the top-level application depends on. + +However, high-level packages, like Iron or Piston, may want the ability to +curate a number of packages for easy installation. The current Cargo system +allows them to curate a number of mandatory dependencies into a single package +for easy installation. + +In some cases, packages may want to provide additional curation for optional +dependencies: + +* grouping a number of low-level optional dependencies together into a single + high-level feature; +* specifying packages that are recommended (or suggested) to be included by + users of the package; and +* including a feature (like `secure-password` in the motivating example) that + will only work if an optional dependency is available, and would be difficult + to implement as a separate package (for example, it may be overly difficult to + design an IO package to be completely decoupled from OpenSSL, with opt-in via + the inclusion of a separate package). + +In almost all cases, it is an antipattern to use these features outside of +high-level packages that are designed for curation. If a feature is optional, it +can almost certainly be expressed as a separate package. + +### The `[workspace]` section + +Projects can define a workspace which is a set of crates that will all share the +same `Cargo.lock` and output directory. The `[workspace]` table can be defined +as: + +```toml +[workspace] + +# Optional key, inferred if not present +members = ["path/to/member1", "path/to/member2", "path/to/member3/*"] + +# Optional key, empty if not present +exclude = ["path1", "path/to/dir2"] +``` + +Workspaces were added to Cargo as part [RFC 1525] and have a number of +properties: + +* A workspace can contain multiple crates where one of them is the root crate. +* The root crate's `Cargo.toml` contains the `[workspace]` table, but is not + required to have other configuration. +* Whenever any crate in the workspace is compiled, output is placed next to the + root crate's `Cargo.toml`. +* The lock file for all crates in the workspace resides next to the root crate's + `Cargo.toml`. +* The `[patch]` and `[replace]` sections in `Cargo.toml` are only recognized + at the workspace root crate, they are ignored in member crates' manifests. + +[RFC 1525]: https://github.com/rust-lang/rfcs/blob/master/text/1525-cargo-workspace.md + +The root crate of a workspace, indicated by the presence of `[workspace]` in its +manifest, is responsible for defining the entire workspace. All `path` +dependencies residing in the workspace directory become members. You can add +additional packages to the workspace by listing them in the `members` key. Note +that members of the workspaces listed explicitly will also have their path +dependencies included in the workspace. Sometimes a project may have a lot of +workspace members and it can be onerous to keep up to date. The path dependency +can also use [globs][globs] to match multiple paths. Finally, the `exclude` +key can be used to blacklist paths from being included in a workspace. This can +be useful if some path dependencies aren't desired to be in the workspace at +all. + +The `package.workspace` manifest key (described above) is used in member crates +to point at a workspace's root crate. If this key is omitted then it is inferred +to be the first crate whose manifest contains `[workspace]` upwards in the +filesystem. + +A crate may either specify `package.workspace` or specify `[workspace]`. That +is, a crate cannot both be a root crate in a workspace (contain `[workspace]`) +and also be a member crate of another workspace (contain `package.workspace`). + +Most of the time workspaces will not need to be dealt with as `cargo new` and +`cargo init` will handle workspace configuration automatically. + +#TODO: move this to a more appropriate place +### The project layout + +If your project is an executable, name the main source file `src/main.rs`. If it +is a library, name the main source file `src/lib.rs`. + +Cargo will also treat any files located in `src/bin/*.rs` as executables. If your +executable consists of more than just one source file, you might also use a directory +inside `src/bin` containing a `main.rs` file which will be treated as an executable +with a name of the parent directory. +Do note, however, once you add a `[[bin]]` section ([see +below](#configuring-a-target)), Cargo will no longer automatically build files +located in `src/bin/*.rs`. Instead you must create a `[[bin]]` section for +each file you want to build. + +Your project can optionally contain folders named `examples`, `tests`, and +`benches`, which Cargo will treat as containing examples, +integration tests, and benchmarks respectively. + +```notrust +▾ src/ # directory containing source files + lib.rs # the main entry point for libraries and packages + main.rs # the main entry point for projects producing executables + ▾ bin/ # (optional) directory containing additional executables + *.rs + ▾ */ # (optional) directories containing multi-file executables + main.rs +▾ examples/ # (optional) examples + *.rs +▾ tests/ # (optional) integration tests + *.rs +▾ benches/ # (optional) benchmarks + *.rs +``` + +To structure your code after you've created the files and folders for your +project, you should remember to use Rust's module system, which you can read +about in [the book](https://doc.rust-lang.org/book/crates-and-modules.html). + +### Examples + +Files located under `examples` are example uses of the functionality provided by +the library. When compiled, they are placed in the `target/examples` directory. + +They can compile either as executables (with a `main()` function) or libraries +and pull in the library by using `extern crate `. They are +compiled when you run your tests to protect them from bitrotting. + +You can run individual executable examples with the command `cargo run --example +`. + +Specify `crate-type` to make an example be compiled as a library: + +```toml +[[example]] +name = "foo" +crate-type = ["staticlib"] +``` + +You can build individual library examples with the command `cargo build +--example `. + +### Tests + +When you run `cargo test`, Cargo will: + +* compile and run your library’s unit tests, which are in the files reachable + from `lib.rs` (naturally, any sections marked with `#[cfg(test)]` will be + considered at this stage); +* compile and run your library’s documentation tests, which are embedded inside + of documentation blocks; +* compile and run your library’s [integration tests](#integration-tests); and +* compile your library’s examples. + +#### Integration tests + +Each file in `tests/*.rs` is an integration test. When you run `cargo test`, +Cargo will compile each of these files as a separate crate. The crate can link +to your library by using `extern crate `, like any other code that +depends on it. + +Cargo will not automatically compile files inside subdirectories of `tests`, but +an integration test can import modules from these directories as usual. For +example, if you want several integration tests to share some code, you can put +the shared code in `tests/common/mod.rs` and then put `mod common;` in each of +the test files. + +### Configuring a target + +All of the `[[bin]]`, `[lib]`, `[[bench]]`, `[[test]]`, and `[[example]]` +sections support similar configuration for specifying how a target should be +built. The double-bracket sections like `[[bin]]` are array-of-table of +[TOML](https://github.com/toml-lang/toml#array-of-tables), which means you can +write more than one `[[bin]]` section to make several executables in your crate. + +The example below uses `[lib]`, but it also applies to all other sections +as well. All values listed are the defaults for that option unless otherwise +specified. + +```toml +[package] +# ... + +[lib] +# The name of a target is the name of the library that will be generated. This +# is defaulted to the name of the package or project, with any dashes replaced +# with underscores. (Rust `extern crate` declarations reference this name; +# therefore the value must be a valid Rust identifier to be usable.) +name = "foo" + +# This field points at where the crate is located, relative to the `Cargo.toml`. +path = "src/lib.rs" + +# A flag for enabling unit tests for this target. This is used by `cargo test`. +test = true + +# A flag for enabling documentation tests for this target. This is only relevant +# for libraries, it has no effect on other sections. This is used by +# `cargo test`. +doctest = true + +# A flag for enabling benchmarks for this target. This is used by `cargo bench`. +bench = true + +# A flag for enabling documentation of this target. This is used by `cargo doc`. +doc = true + +# If the target is meant to be a compiler plugin, this field must be set to true +# for Cargo to correctly compile it and make it available for all dependencies. +plugin = false + +# If the target is meant to be a "macros 1.1" procedural macro, this field must +# be set to true. +proc-macro = false + +# If set to false, `cargo test` will omit the `--test` flag to rustc, which +# stops it from generating a test harness. This is useful when the binary being +# built manages the test runner itself. +harness = true +``` + +#### The `required-features` field (optional) + +The `required-features` field specifies which features the target needs in order +to be built. If any of the required features are not selected, the target will +be skipped. This is only relevant for the `[[bin]]`, `[[bench]]`, `[[test]]`, +and `[[example]]` sections, it has no effect on `[lib]`. + +```toml +[features] +# ... +postgres = [] +sqlite = [] +tools = [] + +[[bin]] +# ... +required-features = ["postgres", "tools"] +``` + +#### Building dynamic or static libraries + +If your project produces a library, you can specify which kind of library to +build by explicitly listing the library in your `Cargo.toml`: + +```toml +# ... + +[lib] +name = "..." +crate-type = ["dylib"] # could be `staticlib` as well +``` + +The available options are `dylib`, `rlib`, `staticlib`, `cdylib`, and +`proc-macro`. You should only use this option in a project. Cargo will always +compile packages (dependencies) based on the requirements of the project that +includes them. + +You can read more about the different crate types in the +[Rust Reference Manual](https://doc.rust-lang.org/reference/linkage.html) + +### The `[patch]` Section + +This section of Cargo.toml can be used to [override dependencies][replace] with +other copies. The syntax is similar to the `[dependencies]` section: + +```toml +[patch.crates-io] +foo = { git = 'https://github.com/example/foo' } +bar = { path = 'my/local/bar' } +``` + +The `[patch]` table is made of dependency-like sub-tables. Each key after +`[patch]` is a URL of the source that's being patched, or `crates-io` if +you're modifying the https://crates.io registry. In the example above +`crates-io` could be replaced with a git URL such as +`https://github.com/rust-lang-nursery/log`. + +Each entry in these tables is a normal dependency specification, the same as +found in the `[dependencies]` section of the manifest. The dependencies listed +in the `[patch]` section are resolved and used to patch the source at the +URL specified. The above manifest snippet patches the `crates-io` source (e.g. +crates.io itself) with the `foo` crate and `bar` crate. + +Sources can be patched with versions of crates that do not exist, and they can +also be patched with versions of crates that already exist. If a source is +patched with a crate version that already exists in the source, then the +source's original crate is replaced. + +More information about overriding dependencies can be found in the [overriding +dependencies][replace] section of the documentation and [RFC 1969] for the +technical specification of this feature. Note that the `[patch]` feature will +first become available in Rust 1.20, set to be released on 2017-08-31. + +[RFC 1969]: https://github.com/rust-lang/rfcs/pull/1969 +[replace]: 03-01-specifying-dependencies.html#overriding-dependencies + +### The `[replace]` Section + +This section of Cargo.toml can be used to [override dependencies][replace] with +other copies. The syntax is similar to the `[dependencies]` section: + +```toml +[replace] +"foo:0.1.0" = { git = 'https://github.com/example/foo' } +"bar:1.0.2" = { path = 'my/local/bar' } +``` + +Each key in the `[replace]` table is a [package id +specification](03-07-pkgid-spec.html) which allows arbitrarily choosing a node in the +dependency graph to override. The value of each key is the same as the +`[dependencies]` syntax for specifying dependencies, except that you can't +specify features. Note that when a crate is overridden the copy it's overridden +with must have both the same name and version, but it can come from a different +source (e.g. git or a local path). + +More information about overriding dependencies can be found in the [overriding +dependencies][replace] section of the documentation. diff --git a/src/doc/book/src/03-03-config.md b/src/doc/book/src/03-03-config.md new file mode 100644 index 00000000000..03ed5b9f8e9 --- /dev/null +++ b/src/doc/book/src/03-03-config.md @@ -0,0 +1,136 @@ +## Configuration + +This document will explain how Cargo’s configuration system works, as well as +available keys or configuration. For configuration of a project through its +manifest, see the [manifest format](03-02-manifest.html). + +### Hierarchical structure + +Cargo allows to have local configuration for a particular project or global +configuration (like git). Cargo also extends this ability to a hierarchical +strategy. If, for example, Cargo were invoked in `/home/foo/bar/baz`, then the +following configuration files would be probed for: + +* `/home/foo/bar/baz/.cargo/config` +* `/home/foo/bar/.cargo/config` +* `/home/foo/.cargo/config` +* `/home/.cargo/config` +* `/.cargo/config` + +With this structure you can specify local configuration per-project, and even +possibly check it into version control. You can also specify personal default +with a configuration file in your home directory. + +### Configuration format + +All configuration is currently in the [TOML format][toml] (like the manifest), +with simple key-value pairs inside of sections (tables) which all get merged +together. + +[toml]: https://github.com/toml-lang/toml + +### Configuration keys + +All of the following keys are optional, and their defaults are listed as their +value unless otherwise noted. + +Key values that specify a tool may be given as an absolute path, a relative path +or as a pathless tool name. Absolute paths and pathless tool names are used as +given. Relative paths are resolved relative to the parent directory of the +`.cargo` directory of the config file that the value resides within. + +```toml +# An array of paths to local repositories which are to be used as overrides for +# dependencies. For more information see the Specifying Dependencies guide. +paths = ["/path/to/override"] + +[cargo-new] +# This is your name/email to place in the `authors` section of a new Cargo.toml +# that is generated. If not present, then `git` will be probed, and if that is +# not present then `$USER` and `$EMAIL` will be used. +name = "..." +email = "..." + +# By default `cargo new` will initialize a new Git repository. This key can be +# set to `hg` to create a Mercurial repository, or `none` to disable this +# behavior. +vcs = "none" + +# For the following sections, $triple refers to any valid target triple, not the +# literal string "$triple", and it will apply whenever that target triple is +# being compiled to. 'cfg(...)' refers to the Rust-like `#[cfg]` syntax for +# conditional compilation. +[target] +# For Cargo builds which do not mention --target, this is the linker +# which is passed to rustc (via `-C linker=`). By default this flag is not +# passed to the compiler. +linker = ".." + +[target.$triple] +# Similar to the above linker configuration, but this only applies to +# when the `$triple` is being compiled for. +linker = ".." +# custom flags to pass to all compiler invocations that target $triple +# this value overrides build.rustflags when both are present +rustflags = ["..", ".."] + +[target.'cfg(...)'] +# Similar for the $triple configuration, but using the `cfg` syntax. +# If several `cfg` and $triple targets are candidates, then the rustflags +# are concatenated. The `cfg` syntax only applies to rustflags, and not to +# linker. +rustflags = ["..", ".."] + +# Configuration keys related to the registry +[registry] +index = "..." # URL of the registry index (defaults to the central repository) +token = "..." # Access token (found on the central repo’s website) + +[http] +proxy = "host:port" # HTTP proxy to use for HTTP requests (defaults to none) + # in libcurl format, e.g. "socks5h://host:port" +timeout = 60000 # Timeout for each HTTP request, in milliseconds +cainfo = "cert.pem" # Path to Certificate Authority (CA) bundle (optional) +check-revoke = true # Indicates whether SSL certs are checked for revocation + +[build] +jobs = 1 # number of parallel jobs, defaults to # of CPUs +rustc = "rustc" # the rust compiler tool +rustdoc = "rustdoc" # the doc generator tool +target = "triple" # build for the target triple +target-dir = "target" # path of where to place all generated artifacts +rustflags = ["..", ".."] # custom flags to pass to all compiler invocations + +[term] +verbose = false # whether cargo provides verbose output +color = 'auto' # whether cargo colorizes output + +# Network configuration +[net] +retry = 2 # number of times a network call will automatically retried + +# Alias cargo commands. The first 3 aliases are built in. If your +# command requires grouped whitespace use the list format. +[alias] +b = "build" +t = "test" +r = "run" +rr = "run --release" +space_example = ["run", "--release", "--", "\"command list\""] +``` + +### Environment variables + +Cargo can also be configured through environment variables in addition to the +TOML syntax above. For each configuration key above of the form `foo.bar` the +environment variable `CARGO_FOO_BAR` can also be used to define the value. For +example the `build.jobs` key can also be defined by `CARGO_BUILD_JOBS`. + +Environment variables will take precedent over TOML configuration, and currently +only integer, boolean, and string keys are supported to be defined by +environment variables. + +In addition to the system above, Cargo recognizes a few other specific +[environment variables][env]. + +[env]: 03-04-environment-variables.html diff --git a/src/doc/book/src/03-04-environment-variables.md b/src/doc/book/src/03-04-environment-variables.md new file mode 100644 index 00000000000..aed2ca58673 --- /dev/null +++ b/src/doc/book/src/03-04-environment-variables.md @@ -0,0 +1,121 @@ +## Environment Variables + +Cargo sets and reads a number of environment variables which your code can detect +or override. Here is a list of the variables Cargo sets, organized by when it interacts +with them: + +### Environment variables Cargo reads + +You can override these environment variables to change Cargo's behavior on your +system: + +* `CARGO_HOME` - Cargo maintains a local cache of the registry index and of git + checkouts of crates. By default these are stored under `$HOME/.cargo`, but + this variable overrides the location of this directory. Once a crate is cached + it is not removed by the clean command. +* `CARGO_TARGET_DIR` - Location of where to place all generated artifacts, + relative to the current working directory. +* `RUSTC` - Instead of running `rustc`, Cargo will execute this specified + compiler instead. +* `RUSTC_WRAPPER` - Instead of simply running `rustc`, Cargo will execute this + specified wrapper instead, passing as its commandline arguments the rustc + invocation, with the first argument being rustc. +* `RUSTDOC` - Instead of running `rustdoc`, Cargo will execute this specified + `rustdoc` instance instead. +* `RUSTFLAGS` - A space-separated list of custom flags to pass to all compiler + invocations that Cargo performs. In contrast with `cargo rustc`, this is + useful for passing a flag to *all* compiler instances. + +Note that Cargo will also read environment variables for `.cargo/config` +configuration values, as described in [that documentation][config-env] + +[config-env]: 03-03-config.html#environment-variables + +### Environment variables Cargo sets for crates + +Cargo exposes these environment variables to your crate when it is compiled. +Note that this applies for test binaries as well. +To get the value of any of these variables in a Rust program, you can use +the `env!` macro: + +``` +let version = env!("CARGO_PKG_VERSION"); +``` + +`version` will now contain the value of `CARGO_PKG_VERSION`. + +* `CARGO` - Path to the `cargo` binary performing the build. +* `CARGO_MANIFEST_DIR` - The directory containing the manifest of your package. +* `CARGO_PKG_VERSION` - The full version of your package. +* `CARGO_PKG_VERSION_MAJOR` - The major version of your package. +* `CARGO_PKG_VERSION_MINOR` - The minor version of your package. +* `CARGO_PKG_VERSION_PATCH` - The patch version of your package. +* `CARGO_PKG_VERSION_PRE` - The pre-release version of your package. +* `CARGO_PKG_AUTHORS` - Colon separated list of authors from the manifest of your package. +* `CARGO_PKG_NAME` - The name of your package. +* `CARGO_PKG_DESCRIPTION` - The description of your package. +* `CARGO_PKG_HOMEPAGE` - The home page of your package. +* `OUT_DIR` - If the package has a build script, this is set to the folder where the build + script should place its output. See below for more information. + +### Environment variables Cargo sets for build scripts + +Cargo sets several environment variables when build scripts are run. Because these variables +are not yet set when the build script is compiled, the above example using `env!` won't work +and instead you'll need to retrieve the values when the build script is run: + +``` +use std::env; +let out_dir = env::var("OUT_DIR").unwrap(); +``` + +`out_dir` will now contain the value of `OUT_DIR`. + +* `CARGO_MANIFEST_DIR` - The directory containing the manifest for the package + being built (the package containing the build + script). Also note that this is the value of the + current working directory of the build script when it + starts. +* `CARGO_MANIFEST_LINKS` - the manifest `links` value. +* `CARGO_FEATURE_` - For each activated feature of the package being + built, this environment variable will be present + where `` is the name of the feature uppercased + and having `-` translated to `_`. +* `CARGO_CFG_` - For each [configuration option][configuration] of the + package being built, this environment variable will + contain the value of the configuration, where `` is + the name of the configuration uppercased and having `-` + translated to `_`. + Boolean configurations are present if they are set, and + not present otherwise. + Configurations with multiple values are joined to a + single variable with the values delimited by `,`. +* `OUT_DIR` - the folder in which all output should be placed. This folder is + inside the build directory for the package being built, and it is + unique for the package in question. +* `TARGET` - the target triple that is being compiled for. Native code should be + compiled for this triple. Some more information about target + triples can be found in [clang’s own documentation][clang]. +* `HOST` - the host triple of the rust compiler. +* `NUM_JOBS` - the parallelism specified as the top-level parallelism. This can + be useful to pass a `-j` parameter to a system like `make`. +* `OPT_LEVEL`, `DEBUG` - values of the corresponding variables for the + profile currently being built. +* `PROFILE` - `release` for release builds, `debug` for other builds. +* `DEP__` - For more information about this set of environment + variables, see build script documentation about [`links`][links]. +* `RUSTC`, `RUSTDOC` - the compiler and documentation generator that Cargo has + resolved to use, passed to the build script so it might + use it as well. + +[links]: 03-05-build-scripts.html#the-links-manifest-key +[profile]: 03-02-manifest.html#the-profile-sections +[configuration]: https://doc.rust-lang.org/reference/attributes.html#conditional-compilation +[clang]:http://clang.llvm.org/docs/CrossCompilation.html#target-triple + +### Environment variables Cargo sets for 3rd party subcommands + +Cargo exposes this environment variable to 3rd party subcommands +(ie. programs named `cargo-foobar` placed in `$PATH`): + +* `CARGO` - Path to the `cargo` binary performing the build. diff --git a/src/doc/book/src/03-05-build-scripts.md b/src/doc/book/src/03-05-build-scripts.md new file mode 100644 index 00000000000..39f66fbdf9a --- /dev/null +++ b/src/doc/book/src/03-05-build-scripts.md @@ -0,0 +1,536 @@ +## Build Script Support + +Some packages need to compile third-party non-Rust code, for example C +libraries. Other packages need to link to C libraries which can either be +located on the system or possibly need to be built from source. Others still +need facilities for functionality such as code generation before building (think +parser generators). + +Cargo does not aim to replace other tools that are well-optimized for +these tasks, but it does integrate with them with the `build` configuration +option. + +```toml +[package] +# ... +build = "build.rs" +``` + +The Rust file designated by the `build` command (relative to the package root) +will be compiled and invoked before anything else is compiled in the package, +allowing your Rust code to depend on the built or generated artifacts. Note +that there is no default value for `build`, it must be explicitly specified if +required. + +Some example use cases of the build command are: + +* Building a bundled C library. +* Finding a C library on the host system. +* Generating a Rust module from a specification. +* Performing any platform-specific configuration needed for the crate. + +Each of these use cases will be detailed in full below to give examples of how +the build command works. + +### Inputs to the Build Script + +When the build script is run, there are a number of inputs to the build script, +all passed in the form of [environment variables][env]. + +In addition to environment variables, the build script’s current directory is +the source directory of the build script’s package. + +[env]: 03-04-environment-variables.html + +### Outputs of the Build Script + +All the lines printed to stdout by a build script are written to a file like +`target/debug/build//output` (the precise location may depend on your +configuration). Any line that starts with `cargo:` is interpreted directly by +Cargo. This line must be of the form `cargo:key=value`, like the examples +below: + +```notrust +# specially recognized by Cargo +cargo:rustc-link-lib=static=foo +cargo:rustc-link-search=native=/path/to/foo +cargo:rustc-cfg=foo +# arbitrary user-defined metadata +cargo:root=/path/to/foo +cargo:libdir=/path/to/foo/lib +cargo:include=/path/to/foo/include +``` + +There are a few special keys that Cargo recognizes, some affecting how the +crate is built: + +* `rustc-link-lib=[KIND=]NAME` indicates that the specified value is a library + name and should be passed to the compiler as a `-l` flag. The optional `KIND` + can be one of `static`, `dylib` (the default), or `framework`, see + `rustc --help` for more details. +* `rustc-link-search=[KIND=]PATH` indicates the specified value is a library + search path and should be passed to the compiler as a `-L` flag. The optional + `KIND` can be one of `dependency`, `crate`, `native`, `framework` or `all` + (the default), see `rustc --help` for more details. +* `rustc-flags=FLAGS` is a set of flags passed to the compiler, only `-l` and + `-L` flags are supported. +* `rustc-cfg=FEATURE` indicates that the specified feature will be passed as a + `--cfg` flag to the compiler. This is often useful for performing compile-time + detection of various features. +* `rerun-if-changed=PATH` is a path to a file or directory which indicates that + the build script should be re-run if it changes (detected by a more-recent + last-modified timestamp on the file). Normally build scripts are re-run if + any file inside the crate root changes, but this can be used to scope changes + to just a small set of files. (If this path points to a directory the entire + directory will not be traversed for changes -- only changes to the timestamp + of the directory itself (which corresponds to some types of changes within the + directory, depending on platform) will trigger a rebuild. To request a re-run + on any changes within an entire directory, print a line for the directory and + another line for everything inside it, recursively.) + Note that if the build script itself (or one of its dependencies) changes, + then it's rebuilt and rerun unconditionally, so + `cargo:rerun-if-changed=build.rs` is almost always redundant (unless you + want to ignore changes in all other files except for `build.rs`). +* `warning=MESSAGE` is a message that will be printed to the main console after + a build script has finished running. Warnings are only shown for path + dependencies (that is, those you're working on locally), so for example + warnings printed out in crates.io crates are not emitted by default. + +Any other element is a user-defined metadata that will be passed to +dependents. More information about this can be found in the [`links`][links] +section. + +[links]: #the-links-manifest-key + +### Build Dependencies + +Build scripts are also allowed to have dependencies on other Cargo-based crates. +Dependencies are declared through the `build-dependencies` section of the +manifest. + +```toml +[build-dependencies] +foo = { git = "https://github.com/your-packages/foo" } +``` + +The build script **does not** have access to the dependencies listed in the +`dependencies` or `dev-dependencies` section (they’re not built yet!). All build +dependencies will also not be available to the package itself unless explicitly +stated as so. + +### The `links` Manifest Key + +In addition to the manifest key `build`, Cargo also supports a `links` manifest +key to declare the name of a native library that is being linked to: + +```toml +[package] +# ... +links = "foo" +build = "build.rs" +``` + +This manifest states that the package links to the `libfoo` native library, and +it also has a build script for locating and/or building the library. Cargo +requires that a `build` command is specified if a `links` entry is also +specified. + +The purpose of this manifest key is to give Cargo an understanding about the set +of native dependencies that a package has, as well as providing a principled +system of passing metadata between package build scripts. + +Primarily, Cargo requires that there is at most one package per `links` value. +In other words, it’s forbidden to have two packages link to the same native +library. Note, however, that there are [conventions in place][star-sys] to +alleviate this. + +[star-sys]: #-sys-packages + +As mentioned above in the output format, each build script can generate an +arbitrary set of metadata in the form of key-value pairs. This metadata is +passed to the build scripts of **dependent** packages. For example, if `libbar` +depends on `libfoo`, then if `libfoo` generates `key=value` as part of its +metadata, then the build script of `libbar` will have the environment variables +`DEP_FOO_KEY=value`. + +Note that metadata is only passed to immediate dependents, not transitive +dependents. The motivation for this metadata passing is outlined in the linking +to system libraries case study below. + +### Overriding Build Scripts + +If a manifest contains a `links` key, then Cargo supports overriding the build +script specified with a custom library. The purpose of this functionality is to +prevent running the build script in question altogether and instead supply the +metadata ahead of time. + +To override a build script, place the following configuration in any acceptable +Cargo [configuration location](03-03-config.html). + +```toml +[target.x86_64-unknown-linux-gnu.foo] +rustc-link-search = ["/path/to/foo"] +rustc-link-lib = ["foo"] +root = "/path/to/foo" +key = "value" +``` + +This section states that for the target `x86_64-unknown-linux-gnu` the library +named `foo` has the metadata specified. This metadata is the same as the +metadata generated as if the build script had run, providing a number of +key/value pairs where the `rustc-flags`, `rustc-link-search`, and +`rustc-link-lib` keys are slightly special. + +With this configuration, if a package declares that it links to `foo` then the +build script will **not** be compiled or run, and the metadata specified will +instead be used. + +### Case study: Code generation + +Some Cargo packages need to have code generated just before they are compiled +for various reasons. Here we’ll walk through a simple example which generates a +library call as part of the build script. + +First, let’s take a look at the directory structure of this package: + +```notrust +. +├── Cargo.toml +├── build.rs +└── src + └── main.rs + +1 directory, 3 files +``` + +Here we can see that we have a `build.rs` build script and our binary in +`main.rs`. Next, let’s take a look at the manifest: + +```toml +# Cargo.toml + +[package] +name = "hello-from-generated-code" +version = "0.1.0" +authors = ["you@example.com"] +build = "build.rs" +``` + +Here we can see we’ve got a build script specified which we’ll use to generate +some code. Let’s see what’s inside the build script: + +```rust,no_run +// build.rs + +use std::env; +use std::fs::File; +use std::io::Write; +use std::path::Path; + +fn main() { + let out_dir = env::var("OUT_DIR").unwrap(); + let dest_path = Path::new(&out_dir).join("hello.rs"); + let mut f = File::create(&dest_path).unwrap(); + + f.write_all(b" + pub fn message() -> &'static str { + \"Hello, World!\" + } + ").unwrap(); +} +``` + +There’s a couple of points of note here: + +* The script uses the `OUT_DIR` environment variable to discover where the + output files should be located. It can use the process’ current working + directory to find where the input files should be located, but in this case we + don’t have any input files. +* This script is relatively simple as it just writes out a small generated file. + One could imagine that other more fanciful operations could take place such as + generating a Rust module from a C header file or another language definition, + for example. + +Next, let’s peek at the library itself: + +```rust,ignore +// src/main.rs + +include!(concat!(env!("OUT_DIR"), "/hello.rs")); + +fn main() { + println!("{}", message()); +} +``` + +This is where the real magic happens. The library is using the rustc-defined +`include!` macro in combination with the `concat!` and `env!` macros to include +the generated file (`hello.rs`) into the crate’s compilation. + +Using the structure shown here, crates can include any number of generated files +from the build script itself. + +### Case study: Building some native code + +Sometimes it’s necessary to build some native C or C++ code as part of a +package. This is another excellent use case of leveraging the build script to +build a native library before the Rust crate itself. As an example, we’ll create +a Rust library which calls into C to print “Hello, World!”. + +Like above, let’s first take a look at the project layout: + +```notrust +. +├── Cargo.toml +├── build.rs +└── src + ├── hello.c + └── main.rs + +1 directory, 4 files +``` + +Pretty similar to before! Next, the manifest: + +```toml +# Cargo.toml + +[package] +name = "hello-world-from-c" +version = "0.1.0" +authors = ["you@example.com"] +build = "build.rs" +``` + +For now we’re not going to use any build dependencies, so let’s take a look at +the build script now: + +```rust,no_run +// build.rs + +use std::process::Command; +use std::env; +use std::path::Path; + +fn main() { + let out_dir = env::var("OUT_DIR").unwrap(); + + // note that there are a number of downsides to this approach, the comments + // below detail how to improve the portability of these commands. + Command::new("gcc").args(&["src/hello.c", "-c", "-fPIC", "-o"]) + .arg(&format!("{}/hello.o", out_dir)) + .status().unwrap(); + Command::new("ar").args(&["crus", "libhello.a", "hello.o"]) + .current_dir(&Path::new(&out_dir)) + .status().unwrap(); + + println!("cargo:rustc-link-search=native={}", out_dir); + println!("cargo:rustc-link-lib=static=hello"); +} +``` + +This build script starts out by compiling our C file into an object file (by +invoking `gcc`) and then converting this object file into a static library (by +invoking `ar`). The final step is feedback to Cargo itself to say that our +output was in `out_dir` and the compiler should link the crate to `libhello.a` +statically via the `-l static=hello` flag. + +Note that there are a number of drawbacks to this hardcoded approach: + +* The `gcc` command itself is not portable across platforms. For example it’s + unlikely that Windows platforms have `gcc`, and not even all Unix platforms + may have `gcc`. The `ar` command is also in a similar situation. +* These commands do not take cross-compilation into account. If we’re cross + compiling for a platform such as Android it’s unlikely that `gcc` will produce + an ARM executable. + +Not to fear, though, this is where a `build-dependencies` entry would help! The +Cargo ecosystem has a number of packages to make this sort of task much easier, +portable, and standardized. For example, the build script could be written as: + +```rust,ignore +// build.rs + +// Bring in a dependency on an externally maintained `gcc` package which manages +// invoking the C compiler. +extern crate gcc; + +fn main() { + gcc::compile_library("libhello.a", &["src/hello.c"]); +} +``` + +Add a build time dependency on the `gcc` crate with the following addition to +your `Cargo.toml`: + +```toml +[build-dependencies] +gcc = "0.3" +``` + +The [`gcc` crate](https://crates.io/crates/gcc) abstracts a range of build +script requirements for C code: + +* It invokes the appropriate compiler (MSVC for windows, `gcc` for MinGW, `cc` + for Unix platforms, etc.). +* It takes the `TARGET` variable into account by passing appropriate flags to + the compiler being used. +* Other environment variables, such as `OPT_LEVEL`, `DEBUG`, etc., are all + handled automatically. +* The stdout output and `OUT_DIR` locations are also handled by the `gcc` + library. + +Here we can start to see some of the major benefits of farming as much +functionality as possible out to common build dependencies rather than +duplicating logic across all build scripts! + +Back to the case study though, let’s take a quick look at the contents of the +`src` directory: + +```c +// src/hello.c + +#include + +void hello() { + printf("Hello, World!\n"); +} +``` + +```rust,ignore +// src/main.rs + +// Note the lack of the `#[link]` attribute. We’re delegating the responsibility +// of selecting what to link to over to the build script rather than hardcoding +// it in the source file. +extern { fn hello(); } + +fn main() { + unsafe { hello(); } +} +``` + +And there we go! This should complete our example of building some C code from a +Cargo package using the build script itself. This also shows why using a build +dependency can be crucial in many situations and even much more concise! + +We’ve also seen a brief example of how a build script can use a crate as a +dependency purely for the build process and not for the crate itself at runtime. + +### Case study: Linking to system libraries + +The final case study here will be investigating how a Cargo library links to a +system library and how the build script is leveraged to support this use case. + +Quite frequently a Rust crate wants to link to a native library often provided +on the system to bind its functionality or just use it as part of an +implementation detail. This is quite a nuanced problem when it comes to +performing this in a platform-agnostic fashion, and the purpose of a build +script is again to farm out as much of this as possible to make this as easy as +possible for consumers. + +As an example to follow, let’s take a look at one of [Cargo’s own +dependencies][git2-rs], [libgit2][libgit2]. This library has a number of +constraints: + +[git2-rs]: https://github.com/alexcrichton/git2-rs/tree/master/libgit2-sys +[libgit2]: https://github.com/libgit2/libgit2 + +* It has an optional dependency on OpenSSL on Unix to implement the https + transport. +* It has an optional dependency on libssh2 on all platforms to implement the ssh + transport. +* It is often not installed on all systems by default. +* It can be built from source using `cmake`. + +To visualize what’s going on here, let’s take a look at the manifest for the +relevant Cargo package. + +```toml +[package] +name = "libgit2-sys" +version = "0.1.0" +authors = ["..."] +links = "git2" +build = "build.rs" + +[dependencies] +libssh2-sys = { git = "https://github.com/alexcrichton/ssh2-rs" } + +[target.'cfg(unix)'.dependencies] +openssl-sys = { git = "https://github.com/alexcrichton/openssl-sys" } + +# ... +``` + +As the above manifests show, we’ve got a `build` script specified, but it’s +worth noting that this example has a `links` entry which indicates that the +crate (`libgit2-sys`) links to the `git2` native library. + +Here we also see the unconditional dependency on `libssh2` via the +`libssh2-sys` crate, as well as a platform-specific dependency on `openssl-sys` +for \*nix (other variants elided for now). It may seem a little counterintuitive +to express *C dependencies* in the *Cargo manifest*, but this is actually using +one of Cargo’s conventions in this space. + +### `*-sys` Packages + +To alleviate linking to system libraries, Cargo has a *convention* of package +naming and functionality. Any package named `foo-sys` will provide two major +pieces of functionality: + +* The library crate will link to the native library `libfoo`. This will often + probe the current system for `libfoo` before resorting to building from + source. +* The library crate will provide **declarations** for functions in `libfoo`, + but it does **not** provide bindings or higher-level abstractions. + +The set of `*-sys` packages provides a common set of dependencies for linking +to native libraries. There are a number of benefits earned from having this +convention of native-library-related packages: + +* Common dependencies on `foo-sys` alleviates the above rule about one package + per value of `links`. +* A common dependency allows centralizing logic on discovering `libfoo` itself + (or building it from source). +* These dependencies are easily overridable. + +### Building libgit2 + +Now that we’ve got libgit2’s dependencies sorted out, we need to actually write +the build script. We’re not going to look at specific snippets of code here and +instead only take a look at the high-level details of the build script of +`libgit2-sys`. This is not recommending all packages follow this strategy, but +rather just outlining one specific strategy. + +The first step of the build script should do is to query whether libgit2 is +already installed on the host system. To do this we’ll leverage the preexisting +tool `pkg-config` (when its available). We’ll also use a `build-dependencies` +section to refactor out all the `pkg-config` related code (or someone’s already +done that!). + +If `pkg-config` failed to find libgit2, or if `pkg-config` just wasn’t +installed, the next step is to build libgit2 from bundled source code +(distributed as part of `libgit2-sys` itself). There are a few nuances when +doing so that we need to take into account, however: + +* The build system of libgit2, `cmake`, needs to be able to find libgit2’s + optional dependency of libssh2. We’re sure we’ve already built it (it’s a + Cargo dependency), we just need to communicate this information. To do this + we leverage the metadata format to communicate information between build + scripts. In this example the libssh2 package printed out `cargo:root=...` to + tell us where libssh2 is installed at, and we can then pass this along to + cmake with the `CMAKE_PREFIX_PATH` environment variable. + +* We’ll need to handle some `CFLAGS` values when compiling C code (and tell + `cmake` about this). Some flags we may want to pass are `-m64` for 64-bit + code, `-m32` for 32-bit code, or `-fPIC` for 64-bit code as well. + +* Finally, we’ll invoke `cmake` to place all output into the `OUT_DIR` + environment variable, and then we’ll print the necessary metadata to instruct + rustc how to link to libgit2. + +Most of the functionality of this build script is easily refactorable into +common dependencies, so our build script isn’t quite as intimidating as this +description! In reality it’s expected that build scripts are quite succinct by +farming logic such as above to build dependencies. diff --git a/src/doc/book/src/03-06-crates-io.md b/src/doc/book/src/03-06-crates-io.md new file mode 100644 index 00000000000..98ed4eef316 --- /dev/null +++ b/src/doc/book/src/03-06-crates-io.md @@ -0,0 +1,222 @@ +## Publishing on crates.io + +Once you've got a library that you'd like to share with the world, it's time to +publish it on [crates.io]! Publishing a crate is when a specific +version is uploaded to be hosted on [crates.io]. + +Take care when publishing a crate, because a publish is **permanent**. The +version can never be overwritten, and the code cannot be deleted. There is no +limit to the number of versions which can be published, however. + +### Before your first publish + +First thing’s first, you’ll need an account on [crates.io] to acquire +an API token. To do so, [visit the home page][crates.io] and log in via a GitHub +account (required for now). After this, visit your [Account +Settings](https://crates.io/me) page and run the `cargo login` command +specified. + +```notrust +$ cargo login abcdefghijklmnopqrstuvwxyz012345 +``` + +This command will inform Cargo of your API token and store it locally in your +`~/.cargo/config`. Note that this token is a **secret** and should not be shared +with anyone else. If it leaks for any reason, you should regenerate it +immediately. + +### Before publishing a new crate + +Keep in mind that crate names on [crates.io] are allocated on a first-come-first- +serve basis. Once a crate name is taken, it cannot be used for another crate. + +#### Packaging a crate + +The next step is to package up your crate into a format that can be uploaded to +[crates.io]. For this we’ll use the `cargo package` subcommand. This will take +our entire crate and package it all up into a `*.crate` file in the +`target/package` directory. + +```notrust +$ cargo package +``` + +As an added bonus, the `*.crate` will be verified independently of the current +source tree. After the `*.crate` is created, it’s unpacked into +`target/package` and then built from scratch to ensure that all necessary files +are there for the build to succeed. This behavior can be disabled with the +`--no-verify` flag. + +Now’s a good time to take a look at the `*.crate` file to make sure you didn’t +accidentally package up that 2GB video asset, or large data files used for code +generation, integration tests, or benchmarking. There is currently a 10MB +upload size limit on `*.crate` files. So, if the size of `tests` and `benches` +directories and their dependencies are up to a couple of MBs, you can keep them +in your package; otherwsie, better to exclude them. + +Cargo will automatically ignore files ignored by your version control system +when packaging, but if you want to specify an extra set of files to ignore you +can use the `exclude` key in the manifest: + +```toml +[package] +# ... +exclude = [ + "public/assets/*", + "videos/*", +] +``` + +The syntax of each element in this array is what +[rust-lang/glob](https://github.com/rust-lang/glob) accepts. If you’d rather +roll with a whitelist instead of a blacklist, Cargo also supports an `include` +key, which if set, overrides the `exclude` key: + +```toml +[package] +# ... +include = [ + "**/*.rs", + "Cargo.toml", +] +``` + +### Uploading the crate + +Now that we’ve got a `*.crate` file ready to go, it can be uploaded to +[crates.io] with the `cargo publish` command. And that’s it, you’ve now published +your first crate! + +```notrust +$ cargo publish +``` + +If you’d like to skip the `cargo package` step, the `cargo publish` subcommand +will automatically package up the local crate if a copy isn’t found already. + +Be sure to check out the [metadata you can +specify](03-02-manifest.html#package-metadata) to ensure your crate can be +discovered more easily! + +### Publishing a new version of an existing crate + +In order to release a new version, change the `version` value specified in your +`Cargo.toml` manifest. Keep in mind [the semver +rules](03-02-manifest.html#the-version-field). Then optionally run `cargo package` if +you want to inspect the `*.crate` file for the new version before publishing, +and run `cargo publish` to upload the new version. + +### Managing a crates.io-based crate + +Management of crates is primarily done through the command line `cargo` tool +rather than the [crates.io] web interface. For this, there are a few subcommands +to manage a crate. + +#### `cargo yank` + +Occasions may arise where you publish a version of a crate that actually ends up +being broken for one reason or another (syntax error, forgot to include a file, +etc.). For situations such as this, Cargo supports a “yank” of a version of a +crate. + +```notrust +$ cargo yank --vers 1.0.1 +$ cargo yank --vers 1.0.1 --undo +``` + +A yank **does not** delete any code. This feature is not intended for deleting +accidentally uploaded secrets, for example. If that happens, you must reset +those secrets immediately. + +The semantics of a yanked version are that no new dependencies can be created +against that version, but all existing dependencies continue to work. One of the +major goals of [crates.io] is to act as a permanent archive of crates that does +not change over time, and allowing deletion of a version would go against this +goal. Essentially a yank means that all projects with a `Cargo.lock` will not +break, while any future `Cargo.lock` files generated will not list the yanked +version. + +#### `cargo owner` + +A crate is often developed by more than one person, or the primary maintainer +may change over time! The owner of a crate is the only person allowed to publish +new versions of the crate, but an owner may designate additional owners. + +```notrust +$ cargo owner --add my-buddy +$ cargo owner --remove my-buddy +$ cargo owner --add github:rust-lang:owners +$ cargo owner --remove github:rust-lang:owners +``` + +The owner IDs given to these commands must be GitHub user names or GitHub teams. + +If a user name is given to `--add`, that user becomes a “named” owner, with +full rights to the crate. In addition to being able to publish or yank versions +of the crate, they have the ability to add or remove owners, *including* the +owner that made *them* an owner. Needless to say, you shouldn’t make people you +don’t fully trust into a named owner. In order to become a named owner, a user +must have logged into [crates.io] previously. + +If a team name is given to `--add`, that team becomes a “team” owner, with +restricted right to the crate. While they have permission to publish or yank +versions of the crate, they *do not* have the ability to add or remove owners. +In addition to being more convenient for managing groups of owners, teams are +just a bit more secure against owners becoming malicious. + +The syntax for teams is currently `github:org:team` (see examples above). +In order to add a team as an owner one must be a member of that team. No +such restriction applies to removing a team as an owner. + +### GitHub permissions + +Team membership is not something GitHub provides simple public access to, and it +is likely for you to encounter the following message when working with them: + +> It looks like you don’t have permission to query a necessary property from +GitHub to complete this request. You may need to re-authenticate on [crates.io] +to grant permission to read GitHub org memberships. Just go to +https://crates.io/login + +This is basically a catch-all for “you tried to query a team, and one of the +five levels of membership access control denied this”. That is not an +exaggeration. GitHub’s support for team access control is Enterprise Grade. + +The most likely cause of this is simply that you last logged in before this +feature was added. We originally requested *no* permissions from GitHub when +authenticating users, because we didn’t actually ever use the user’s token for +anything other than logging them in. However to query team membership on your +behalf, we now require +[the `read:org` scope](https://developer.github.com/v3/oauth/#scopes). + +You are free to deny us this scope, and everything that worked before teams +were introduced will keep working. However you will never be able to add a team +as an owner, or publish a crate as a team owner. If you ever attempt to do this, +you will get the error above. You may also see this error if you ever try to +publish a crate that you don’t own at all, but otherwise happens to have a team. + +If you ever change your mind, or just aren’t sure if [crates.io] has sufficient +permission, you can always go to https://crates.io/login, which will prompt you +for permission if [crates.io] doesn’t have all the scopes it would like to. + +An additional barrier to querying GitHub is that the organization may be +actively denying third party access. To check this, you can go to: + + https://github.com/organizations/:org/settings/oauth_application_policy + +where `:org` is the name of the organization (e.g. rust-lang). You may see +something like: + +![Organization Access Control](images/org-level-acl.png) + +Where you may choose to explicitly remove [crates.io] from your organization’s +blacklist, or simply press the “Remove Restrictions” button to allow all third +party applications to access this data. + +Alternatively, when [crates.io] requested the `read:org` scope, you could have +explicitly whitelisted [crates.io] querying the org in question by pressing +the “Grant Access” button next to its name: + +![Authentication Access Control](images/auth-level-acl.png) + +[crates.io]: https://crates.io/ diff --git a/src/doc/book/src/03-07-pkgid-spec.md b/src/doc/book/src/03-07-pkgid-spec.md new file mode 100644 index 00000000000..6365c397c42 --- /dev/null +++ b/src/doc/book/src/03-07-pkgid-spec.md @@ -0,0 +1,44 @@ +## Package ID Specifications + +### Package ID specifications + +Subcommands of Cargo frequently need to refer to a particular package within a +dependency graph for various operations like updating, cleaning, building, etc. +To solve this problem, Cargo supports Package ID Specifications. A specification +is a string which is used to uniquely refer to one package within a graph of +packages. + +#### Specification grammar + +The formal grammar for a Package Id Specification is: + +```notrust +pkgid := pkgname + | [ proto "://" ] hostname-and-path [ "#" ( pkgname | semver ) ] +pkgname := name [ ":" semver ] + +proto := "http" | "git" | ... +``` + +Here, brackets indicate that the contents are optional. + +#### Example specifications + +These could all be references to a package `foo` version `1.2.3` from the +registry at `crates.io` + +| pkgid | name | version | url | +|-------------------------------:|:------:|:---------:|:--------------------:| +| `foo` | foo | * | * | +| `foo:1.2.3` | foo | 1.2.3 | * | +| `crates.io/foo` | foo | * | *://crates.io/foo | +| `crates.io/foo#1.2.3` | foo | 1.2.3 | *://crates.io/foo | +| `crates.io/bar#foo:1.2.3` | foo | 1.2.3 | *://crates.io/bar | +| `http://crates.io/foo#1.2.3` | foo | 1.2.3 | http://crates.io/foo | + +#### Brevity of specifications + +The goal of this is to enable both succinct and exhaustive syntaxes for +referring to packages in a dependency graph. Ambiguous references may refer to +one or more packages. Most commands generate an error if more than one package +could be referred to with the same specification. diff --git a/src/doc/book/src/03-08-source-replacement.md b/src/doc/book/src/03-08-source-replacement.md new file mode 100644 index 00000000000..dcb88346d02 --- /dev/null +++ b/src/doc/book/src/03-08-source-replacement.md @@ -0,0 +1,128 @@ +## Replacing sources + +Cargo supports the ability to **replace one source with another** to express +strategies along the lines of mirrors or vendoring dependencies. Configuration +is currently done through the [`.cargo/config` configuration][config] mechanism, +like so: + +[config]: 03-03-config.html + +```toml +# The `source` table is where all keys related to source-replacement +# are stored. +[source] + +# Under the `source` table are a number of other tables whose keys are a +# name for the relevant source. For example this section defines a new +# source, called `my-awesome-source`, which comes from a directory +# located at `vendor` relative to the directory containing this `.cargo/config` +# file +[source.my-awesome-source] +directory = "vendor" + +# The crates.io default source for crates is available under the name +# "crates-io", and here we use the `replace-with` key to indicate that it's +# replaced with our source above. +[source.crates-io] +replace-with = "my-awesome-source" +``` + +With this configuration Cargo attempts to look up all crates in the directory +"vendor" rather than querying the online registry at crates.io. Using source +replacement Cargo can express: + +* Vendoring - custom sources can be defined which represent crates on the local + filesystem. These sources are subsets of the source that they're replacing and + can be checked into projects if necessary. + +* Mirroring - sources can be replaced with an equivalent version which acts as a + cache for crates.io itself. + +Cargo has a core assumption about source replacement that the source code is +exactly the same from both sources. In our above example Cargo assumes that all +of the crates coming from `my-awesome-source` are the exact same as the copies +from `crates-io`. Note that this also means that `my-awesome-source` is not +allowed to have crates which are not present in the `crates-io` source. + +As a consequence, source replacement is not appropriate for situations such as +patching a dependency or a private registry. Cargo supports patching +dependencies through the usage of [the `[replace]` key][replace-section], and +private registry support is planned for a future version of Cargo. + +[replace-section]: 03-02-manifest.html#the-replace-section + +### Configuration + +Configuration of replacement sources is done through [`.cargo/config`][config] +and the full set of available keys are: + +```toml +# Each source has its own table where the key is the name of the source +[source.the-source-name] + +# Indicate that `the-source-name` will be replaced with `another-source`, +# defined elsewhere +replace-with = "another-source" + +# Available kinds of sources that can be specified (described below) +registry = "https://example.com/path/to/index" +local-registry = "path/to/registry" +directory = "path/to/vendor" +``` + +The `crates-io` represents the crates.io online registry (default source of +crates) and can be replaced with: + +```toml +[source.crates-io] +replace-with = 'another-source' +``` + +### Registry Sources + +A "registry source" is one that is the same as crates.io itself. That is, it has +an index served in a git repository which matches the format of the +[crates.io index](https://github.com/rust-lang/crates.io-index). That repository +then has configuration indicating where to download crates from. + +Currently there is not an already-available project for setting up a mirror of +crates.io. Stay tuned though! + +### Local Registry Sources + +A "local registry source" is intended to be a subset of another registry +source, but available on the local filesystem (aka vendoring). Local registries +are downloaded ahead of time, typically sync'd with a `Cargo.lock`, and are +made up of a set of `*.crate` files and an index like the normal registry is. + +The primary way to manage and crate local registry sources is through the +[`cargo-local-registry`][cargo-local-registry] subcommand, available on +crates.io and can be installed with `cargo install cargo-local-registry`. + +[cargo-local-registry]: https://crates.io/crates/cargo-local-registry + +Local registries are contained within one directory and contain a number of +`*.crate` files downloaded from crates.io as well as an `index` directory with +the same format as the crates.io-index project (populated with just entries for +the crates that are present). + +### Directory Sources + +A "directory source" is similar to a local registry source where it contains a +number of crates available on the local filesystem, suitable for vendoring +dependencies. Also like local registries, directory sources can primarily be +managed by an external subcommand, [`cargo-vendor`][cargo-vendor], which can be +installed with `cargo install cargo-vendor`. + +[cargo-vendor]: https://crates.io/crates/cargo-vendor + +Directory sources are distinct from local registries though in that they contain +the unpacked version of `*.crate` files, making it more suitable in some +situations to check everything into source control. A directory source is just a +directory containing a number of other directories which contain the source code +for crates (the unpacked version of `*.crate` files). Currently no restriction +is placed on the name of each directory. + +Each crate in a directory source also has an associated metadata file indicating +the checksum of each file in the crate to protect against accidental +modifications. diff --git a/src/doc/book/src/03-09-external-tools.md b/src/doc/book/src/03-09-external-tools.md new file mode 100644 index 00000000000..125016d01b1 --- /dev/null +++ b/src/doc/book/src/03-09-external-tools.md @@ -0,0 +1,102 @@ +## External tools + +One of the goals of Cargo is simple integration with third-party tools, like +IDEs and other build systems. To make integration easier, Cargo has several +facilities: + +* `cargo metadata` command, which outputs project structure and dependencies + information in JSON, + +* `--message-format` flag, which outputs information about a particular build, + +* support for custom subcommands. + + +### Information about project structure + +You can use `cargo metadata` command to get information about project structure +and dependencies. The output of the command looks like this: + +```text +{ + // Integer version number of the format. + "version": integer, + + // List of packages for this workspace, including dependencies. + "packages": [ + { + // Opaque package identifier. + "id": PackageId, + + "name": string, + + "version": string, + + "source": SourceId, + + // A list of declared dependencies, see `resolve` field for actual dependencies. + "dependencies": [ Dependency ], + + "targets: [ Target ], + + // Path to Cargo.toml + "manifest_path": string, + } + ], + + "workspace_members": [ PackageId ], + + // Dependencies graph. + "resolve": { + "nodes": [ + { + "id": PackageId, + "dependencies": [ PackageId ] + } + ] + } +} +``` + +The format is stable and versioned. When calling `cargo metadata`, you should +pass `--format-version` flag explicitly to avoid forward incompatibility +hazard. + +If you are using Rust, there is [cargo_metadata] crate. + +[cargo_metadata]: https://crates.io/crates/cargo_metadata + + +### Information about build + +When passing `--message=format=json`, Cargo will output the following +information during the build: + +* compiler errors and warnings, + +* produced artifacts, + +* results of the build scripts (for example, native dependencies). + +The output goes to stdout in the JSON object per line format. The `reason` field +distinguishes different kinds of messages. + +Information about dependencies in the Makefile-compatible format is stored in +the `.d` files alongside the artifacts. + + +### Custom subcommands. + +Cargo is designed to be extensible with new subcommands without having to modify +Cargo itself. This is achieved by translating a cargo invocation of the form +cargo `(?[^ ]+)` into an invocation of an external tool +`cargo-${command}` that then needs to be present in one of the user's `$PATH` +directories. + +Custom subcommand may use `CARGO` environment variable to call back to +Cargo. Alternatively, it can link to `cargo` crate as a library, but this +approach has drawbacks: + +* Cargo as a library is unstable, API changes without deprecation, + +* versions of Cargo library and Cargo binary may be different. diff --git a/src/doc/book/src/03-10-policies.md b/src/doc/book/src/03-10-policies.md new file mode 100644 index 00000000000..db71c083ad6 --- /dev/null +++ b/src/doc/book/src/03-10-policies.md @@ -0,0 +1,52 @@ +## Crates.io package policies + +In general, these policies are guidelines. Problems are often contextual, and +exceptional circumstances sometimes require exceptional measures. We plan to +continue to clarify and expand these rules over time as new circumstances +arise. If your problem is not described below, consider [sending us an email]. + +### Package Ownership + +We have a first-come, first-served policy on crate names. Upon publishing a +package, the publisher will be made owner of the package on Crates.io. + +If someone wants to take over a package, and the previous owner agrees, the +existing maintainer can add them as an owner, and the new maintainer can remove +them. If necessary, the team may reach out to inactive maintainers and help +mediate the process of ownership transfer. + +### Removal + +Many questions are specialized instances of a more general form: “Under what +circumstances can a package be removed from Crates.io?” + +The short version is that packages are first-come, first-served, and we won’t +attempt to get into policing what exactly makes a legitimate package. We will +do what the law requires us to do, and address flagrant violations of the Rust +Code of Conduct. + +### Squatting + +We do not have any policies to define 'squatting', and so will not hand over +ownership of a package for that reason. + +### The Law + +For issues such as DMCA violations, trademark and copyright infringement, +Crates.io will respect Mozilla Legal’s decisions with regards to content that +is hosted. + +### Code of Conduct + +The Rust project has a [Code of Conduct] which governs appropriate conduct for +the Rust community. In general, any content on Crates.io that violates the Code +of Conduct may be removed. There are two important, related aspects: + +- We will not be pro-actively monitoring the site for these kinds of violations, + but relying on the community to draw them to our attention. +- “Does this violate the Code of Conduct” is a contextual question that + cannot be directly answered in the hypothetical sense. All of the details + must be taken into consideration in these kinds of situations. + +[Code of Conduct]: https://www.rust-lang.org/conduct.html +[sending us an email]: mailto:help@crates.io diff --git a/src/doc/book/src/SUMMARY.md b/src/doc/book/src/SUMMARY.md new file mode 100644 index 00000000000..8b2e4cfbe72 --- /dev/null +++ b/src/doc/book/src/SUMMARY.md @@ -0,0 +1,25 @@ +# Summary + +* [Getting Started](getting-started.md) + * [Installation](01-01-installation.md) + * [First steps with Cargo](01-02-first-steps.md) +* [Guide](guide.md) + * [Why Cargo exists](02-01-why-cargo-exists.md) + * [Creating a new project](02-02-creating-a-new-project.md) + * [Working on an existing Cargo project](02-03-working-on-an-existing-project.md) + * [Dependencies](02-04-dependencies.md) + * [Project layout](02-05-project-layout.md) + * [Tests](02-06-tests.md) + * [Continuous Integration](02-07-continuous-integration.md) +* [Cargo In Depth](cargo-in-depth.md) + * [Specifying Dependencies](03-01-specifying-dependencies.md) + * [Cargo.toml Format](03-02-manifest.md) + * [Configuration](03-03-config.md) + * [Environment Variables](03-04-environment-variables.md) + * [Build Scripts](03-05-build-scripts.md) + * [Publishing on crates.io](03-06-crates-io.md) + * [Package ID specs](03-07-pkgid-spec.md) + * [Source Replacement](03-08-source-replacement.md) + * [External Tools](03-09-external-tools.md) + * [Policies](03-10-policies.md) +* [FAQ](faq.md) diff --git a/src/doc/book/src/cargo-in-depth.md b/src/doc/book/src/cargo-in-depth.md new file mode 100644 index 00000000000..bdaee585120 --- /dev/null +++ b/src/doc/book/src/cargo-in-depth.md @@ -0,0 +1,4 @@ +## Cargo In Depth + +* [Specifying Dependencies](03-01-specifying-dependencies.html) +* [Cargo.toml Format](03-02-manifest.html) diff --git a/src/doc/book/src/faq.md b/src/doc/book/src/faq.md new file mode 100644 index 00000000000..f2da9f39717 --- /dev/null +++ b/src/doc/book/src/faq.md @@ -0,0 +1,193 @@ +## Frequently Asked Questions + +### Is the plan to use GitHub as a package repository? + +No. The plan for Cargo is to use [crates.io], like npm or Rubygems do with +npmjs.org and rubygems.org. + +We plan to support git repositories as a source of packages forever, +because they can be used for early development and temporary patches, +even when people use the registry as the primary source of packages. + +### Why build crates.io rather than use GitHub as a registry? + +We think that it’s very important to support multiple ways to download +packages, including downloading from GitHub and copying packages into +your project itself. + +That said, we think that [crates.io] offers a number of important benefits, and +will likely become the primary way that people download packages in Cargo. + +For precedent, both Node.js’s [npm][1] and Ruby’s [bundler][2] support both a +central registry model as well as a Git-based model, and most packages +are downloaded through the registry in those ecosystems, with an +important minority of packages making use of git-based packages. + +[1]: https://www.npmjs.org +[2]: https://bundler.io + +Some of the advantages that make a central registry popular in other +languages include: + +* **Discoverability**. A central registry provides an easy place to look + for existing packages. Combined with tagging, this also makes it + possible for a registry to provide ecosystem-wide information, such as a + list of the most popular or most-depended-on packages. +* **Speed**. A central registry makes it possible to easily fetch just + the metadata for packages quickly and efficiently, and then to + efficiently download just the published package, and not other bloat + that happens to exist in the repository. This adds up to a significant + improvement in the speed of dependency resolution and fetching. As + dependency graphs scale up, downloading all of the git repositories bogs + down fast. Also remember that not everybody has a high-speed, + low-latency Internet connection. + +### Will Cargo work with C code (or other languages)? + +Yes! + +Cargo handles compiling Rust code, but we know that many Rust projects +link against C code. We also know that there are decades of tooling +built up around compiling languages other than Rust. + +Our solution: Cargo allows a package to [specify a script](03-05-build-scripts.html) +(written in Rust) to run before invoking `rustc`. Rust is leveraged to +implement platform-specific configuration and refactor out common build +functionality among packages. + +### Can Cargo be used inside of `make` (or `ninja`, or ...) + +Indeed. While we intend Cargo to be useful as a standalone way to +compile Rust projects at the top-level, we know that some people will +want to invoke Cargo from other build tools. + +We have designed Cargo to work well in those contexts, paying attention +to things like error codes and machine-readable output modes. We still +have some work to do on those fronts, but using Cargo in the context of +conventional scripts is something we designed for from the beginning and +will continue to prioritize. + +### Does Cargo handle multi-platform projects or cross-compilation? + +Rust itself provides facilities for configuring sections of code based +on the platform. Cargo also supports [platform-specific +dependencies][target-deps], and we plan to support more per-platform +configuration in `Cargo.toml` in the future. + +[target-deps]: 03-02-manifest.html#the-dependencies-section + +In the longer-term, we’re looking at ways to conveniently cross-compile +projects using Cargo. + +### Does Cargo support environments, like `production` or `test`? + +We support environments through the use of [profiles][profile] to support: + +[profile]: 03-02-manifest.html#the-profile-sections + +* environment-specific flags (like `-g --opt-level=0` for development + and `--opt-level=3` for production). +* environment-specific dependencies (like `hamcrest` for test assertions). +* environment-specific `#[cfg]` +* a `cargo test` command + +### Does Cargo work on Windows? + +Yes! + +All commits to Cargo are required to pass the local test suite on Windows. +If, however, you find a Windows issue, we consider it a bug, so [please file an +issue][3]. + +[3]: https://github.com/rust-lang/cargo/issues + +### Why do binaries have `Cargo.lock` in version control, but not libraries? + +The purpose of a `Cargo.lock` is to describe the state of the world at the time +of a successful build. It is then used to provide deterministic builds across +whatever machine is building the project by ensuring that the exact same +dependencies are being compiled. + +This property is most desirable from applications and projects which are at the +very end of the dependency chain (binaries). As a result, it is recommended that +all binaries check in their `Cargo.lock`. + +For libraries the situation is somewhat different. A library is not only used by +the library developers, but also any downstream consumers of the library. Users +dependent on the library will not inspect the library’s `Cargo.lock` (even if it +exists). This is precisely because a library should **not** be deterministically +recompiled for all users of the library. + +If a library ends up being used transitively by several dependencies, it’s +likely that just a single copy of the library is desired (based on semver +compatibility). If all libraries were to check in their `Cargo.lock`, then +multiple copies of the library would be used, and perhaps even a version +conflict. + +In other words, libraries specify semver requirements for their dependencies but +cannot see the full picture. Only end products like binaries have a full +picture to decide what versions of dependencies should be used. + +### Can libraries use `*` as a version for their dependencies? + +**As of January 22nd, 2016, [crates.io] rejects all packages (not just libraries) +with wildcard dependency constraints.** + +While libraries _can_, strictly speaking, they should not. A version requirement +of `*` says “This will work with every version ever,” which is never going +to be true. Libraries should always specify the range that they do work with, +even if it’s something as general as “every 1.x.y version.” + +### Why `Cargo.toml`? + +As one of the most frequent interactions with Cargo, the question of why the +configuration file is named `Cargo.toml` arises from time to time. The leading +capital-`C` was chosen to ensure that the manifest was grouped with other +similar configuration files in directory listings. Sorting files often puts +capital letters before lowercase letters, ensuring files like `Makefile` and +`Cargo.toml` are placed together. The trailing `.toml` was chosen to emphasize +the fact that the file is in the [TOML configuration +format](https://github.com/toml-lang/toml). + +Cargo does not allow other names such as `cargo.toml` or `Cargofile` to +emphasize the ease of how a Cargo repository can be identified. An option of +many possible names has historically led to confusion where one case was handled +but others were accidentally forgotten. + +[crates.io]: https://crates.io/ + +### How can Cargo work offline? + +Cargo is often used in situations with limited or no network access such as +airplanes, CI environments, or embedded in large production deployments. Users +are often surprised when Cargo attempts to fetch resources from the network, and +hence the request for Cargo to work offline comes up frequently. + +Cargo, at its heart, will not attempt to access the network unless told to do +so. That is, if no crates comes from crates.io, a git repository, or some other +network location, Cargo will never attempt to make a network connection. As a +result, if Cargo attempts to touch the network, then it's because it needs to +fetch a required resource. + +Cargo is also quite aggressive about caching information to minimize the amount +of network activity. It will guarantee, for example, that if `cargo build` (or +an equivalent) is run to completion then the next `cargo build` is guaranteed to +not touch the network so long as `Cargo.toml` has not been modified in the +meantime. This avoidance of the network boils down to a `Cargo.lock` existing +and a populated cache of the crates reflected in the lock file. If either of +these components are missing, then they're required for the build to succeed and +must be fetched remotely. + +As of Rust 1.11.0 Cargo understands a new flag, `--frozen`, which is an +assertion that it shouldn't touch the network. When passed, Cargo will +immediately return an error if it would otherwise attempt a network request. +The error should include contextual information about why the network request is +being made in the first place to help debug as well. Note that this flag *does +not change the behavior of Cargo*, it simply asserts that Cargo shouldn't touch +the network as a previous command has been run to ensure that network activity +shouldn't be necessary. + +For more information about vendoring, see documentation on [source +replacement][replace]. + +[replace]: 03-08-source-replacement.html diff --git a/src/doc/book/src/favicon.ico b/src/doc/book/src/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..a91ad692c91fb82bb6d16624e84a0cd7791eed24 GIT binary patch literal 5430 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