1# Rust {#rust} 2 3To install the rust compiler and cargo put 4 5```nix 6environment.systemPackages = [ 7 rustc 8 cargo 9]; 10``` 11 12into your `configuration.nix` or bring them into scope with `nix-shell -p rustc cargo`. 13 14For other versions such as daily builds (beta and nightly), 15use either `rustup` from nixpkgs (which will manage the rust installation in your home directory), 16or use Mozilla's [Rust nightlies overlay](#using-the-rust-nightlies-overlay). 17 18## Compiling Rust applications with Cargo 19 20Rust applications are packaged by using the `buildRustPackage` helper from `rustPlatform`: 21 22```nix 23{ lib, rustPlatform }: 24 25rustPlatform.buildRustPackage rec { 26 pname = "ripgrep"; 27 version = "12.1.1"; 28 29 src = fetchFromGitHub { 30 owner = "BurntSushi"; 31 repo = pname; 32 rev = version; 33 sha256 = "1hqps7l5qrjh9f914r5i6kmcz6f1yb951nv4lby0cjnp5l253kps"; 34 }; 35 36 cargoSha256 = "03wf9r2csi6jpa7v5sw5lpxkrk4wfzwmzx7k3991q3bdjzcwnnwp"; 37 38 meta = with lib; { 39 description = "A fast line-oriented regex search tool, similar to ag and ack"; 40 homepage = "https://github.com/BurntSushi/ripgrep"; 41 license = licenses.unlicense; 42 maintainers = [ maintainers.tailhook ]; 43 }; 44} 45``` 46 47`buildRustPackage` requires either the `cargoSha256` or the 48`cargoHash` attribute which is computed over all crate sources of this 49package. `cargoHash256` is used for traditional Nix SHA-256 hashes, 50such as the one in the example above. `cargoHash` should instead be 51used for [SRI](https://www.w3.org/TR/SRI/) hashes. For example: 52 53```nix 54 cargoHash = "sha256-l1vL2ZdtDRxSGvP0X/l3nMw8+6WF67KPutJEzUROjg8="; 55``` 56 57Both types of hashes are permitted when contributing to nixpkgs. The 58Cargo hash is obtained by inserting a fake checksum into the 59expression and building the package once. The correct checksum can 60then be taken from the failed build. A fake hash can be used for 61`cargoSha256` as follows: 62 63```nix 64 cargoSha256 = lib.fakeSha256; 65``` 66 67For `cargoHash` you can use: 68 69```nix 70 cargoHash = lib.fakeHash; 71``` 72 73Per the instructions in the [Cargo Book](https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html) 74best practices guide, Rust applications should always commit the `Cargo.lock` 75file in git to ensure a reproducible build. However, a few packages do not, and 76Nix depends on this file, so if it is missing you can use `cargoPatches` to 77apply it in the `patchPhase`. Consider sending a PR upstream with a note to the 78maintainer describing why it's important to include in the application. 79 80The fetcher will verify that the `Cargo.lock` file is in sync with the `src` 81attribute, and fail the build if not. It will also will compress the vendor 82directory into a tar.gz archive. 83 84The tarball with vendored dependencies contains a directory with the 85package's `name`, which is normally composed of `pname` and 86`version`. This means that the vendored dependencies hash 87(`cargoSha256`/`cargoHash`) is dependent on the package name and 88version. The `cargoDepsName` attribute can be used to use another name 89for the directory of vendored dependencies. For example, the hash can 90be made invariant to the version by setting `cargoDepsName` to 91`pname`: 92 93```nix 94rustPlatform.buildRustPackage rec { 95 pname = "broot"; 96 version = "1.2.0"; 97 98 src = fetchCrate { 99 inherit pname version; 100 sha256 = "1mqaynrqaas82f5957lx31x80v74zwmwmjxxlbywajb61vh00d38"; 101 }; 102 103 cargoHash = "sha256-JmBZcDVYJaK1cK05cxx5BrnGWp4t8ca6FLUbvIot67s="; 104 cargoDepsName = pname; 105 106 # ... 107} 108``` 109 110 111### Cross compilation 112 113By default, Rust packages are compiled for the host platform, just like any 114other package is. The `--target` passed to rust tools is computed from this. 115By default, it takes the `stdenv.hostPlatform.config` and replaces components 116where they are known to differ. But there are ways to customize the argument: 117 118 - To choose a different target by name, define 119 `stdenv.hostPlatform.rustc.config` as that name (a string), and that 120 name will be used instead. 121 122 For example: 123 ```nix 124 import <nixpkgs> { 125 crossSystem = (import <nixpkgs/lib>).systems.examples.armhf-embedded // { 126 rustc.config = "thumbv7em-none-eabi"; 127 }; 128 } 129 ``` 130 will result in: 131 ```shell 132 --target thumbv7em-none-eabi 133 ``` 134 135 - To pass a completely custom target, define 136 `stdenv.hostPlatform.rustc.config` with its name, and 137 `stdenv.hostPlatform.rustc.platform` with the value. The value will be 138 serialized to JSON in a file called 139 `${stdenv.hostPlatform.rustc.config}.json`, and the path of that file 140 will be used instead. 141 142 For example: 143 ```nix 144 import <nixpkgs> { 145 crossSystem = (import <nixpkgs/lib>).systems.examples.armhf-embedded // { 146 rustc.config = "thumb-crazy"; 147 rustc.platform = { foo = ""; bar = ""; }; 148 }; 149 } 150 ``` 151 will result in: 152 ```shell 153 --target /nix/store/asdfasdfsadf-thumb-crazy.json # contains {"foo":"","bar":""} 154 ``` 155 156Finally, as an ad-hoc escape hatch, a computed target (string or JSON file 157path) can be passed directly to `buildRustPackage`: 158 159```nix 160pkgs.rustPlatform.buildRustPackage { 161 /* ... */ 162 target = "x86_64-fortanix-unknown-sgx"; 163} 164``` 165 166This is useful to avoid rebuilding Rust tools, since they are actually target 167agnostic and don't need to be rebuilt. But in the future, we should always 168build the Rust tools and standard library crates separately so there is no 169reason not to take the `stdenv.hostPlatform.rustc`-modifying approach, and the 170ad-hoc escape hatch to `buildRustPackage` can be removed. 171 172Note that currently custom targets aren't compiled with `std`, so `cargo test` 173will fail. This can be ignored by adding `doCheck = false;` to your derivation. 174 175### Running package tests 176 177When using `buildRustPackage`, the `checkPhase` is enabled by default and runs 178`cargo test` on the package to build. To make sure that we don't compile the 179sources twice and to actually test the artifacts that will be used at runtime, 180the tests will be ran in the `release` mode by default. 181 182However, in some cases the test-suite of a package doesn't work properly in the 183`release` mode. For these situations, the mode for `checkPhase` can be changed like 184so: 185 186```nix 187rustPlatform.buildRustPackage { 188 /* ... */ 189 checkType = "debug"; 190} 191``` 192 193Please note that the code will be compiled twice here: once in `release` mode 194for the `buildPhase`, and again in `debug` mode for the `checkPhase`. 195 196Test flags, e.g., `--features xxx/yyy`, can be passed to `cargo test` via the 197`cargoTestFlags` attribute. 198 199Another attribute, called `checkFlags`, is used to pass arguments to the test 200binary itself, as stated 201(here)[https://doc.rust-lang.org/cargo/commands/cargo-test.html]. 202 203#### Tests relying on the structure of the `target/` directory 204 205Some tests may rely on the structure of the `target/` directory. Those tests 206are likely to fail because we use `cargo --target` during the build. This means that 207the artifacts 208[are stored in `target/<architecture>/release/`](https://doc.rust-lang.org/cargo/guide/build-cache.html), 209rather than in `target/release/`. 210 211This can only be worked around by patching the affected tests accordingly. 212 213#### Disabling package-tests 214 215In some instances, it may be necessary to disable testing altogether (with `doCheck = false;`): 216 217* If no tests exist -- the `checkPhase` should be explicitly disabled to skip 218 unnecessary build steps to speed up the build. 219* If tests are highly impure (e.g. due to network usage). 220 221There will obviously be some corner-cases not listed above where it's sensible to disable tests. 222The above are just guidelines, and exceptions may be granted on a case-by-case basis. 223 224However, please check if it's possible to disable a problematic subset of the 225test suite and leave a comment explaining your reasoning. 226 227#### Setting `test-threads` 228 229`buildRustPackage` will use parallel test threads by default, 230sometimes it may be necessary to disable this so the tests run consecutively. 231 232```nix 233rustPlatform.buildRustPackage { 234 /* ... */ 235 dontUseCargoParallelTests = true; 236} 237``` 238 239### Building a package in `debug` mode 240 241By default, `buildRustPackage` will use `release` mode for builds. If a package 242should be built in `debug` mode, it can be configured like so: 243 244```nix 245rustPlatform.buildRustPackage { 246 /* ... */ 247 buildType = "debug"; 248} 249``` 250 251In this scenario, the `checkPhase` will be ran in `debug` mode as well. 252 253### Custom `build`/`install`-procedures 254 255Some packages may use custom scripts for building/installing, e.g. with a `Makefile`. 256In these cases, it's recommended to override the `buildPhase`/`installPhase`/`checkPhase`. 257 258Otherwise, some steps may fail because of the modified directory structure of `target/`. 259 260### Building a crate with an absent or out-of-date Cargo.lock file 261 262`buildRustPackage` needs a `Cargo.lock` file to get all dependencies in the 263source code in a reproducible way. If it is missing or out-of-date one can use 264the `cargoPatches` attribute to update or add it. 265 266```nix 267rustPlatform.buildRustPackage rec { 268 (...) 269 cargoPatches = [ 270 # a patch file to add/update Cargo.lock in the source code 271 ./add-Cargo.lock.patch 272 ]; 273} 274``` 275 276## Compiling non-Rust packages that include Rust code 277 278Several non-Rust packages incorporate Rust code for performance- or 279security-sensitive parts. `rustPlatform` exposes several functions and 280hooks that can be used to integrate Cargo in non-Rust packages. 281 282### Vendoring of dependencies 283 284Since network access is not allowed in sandboxed builds, Rust crate 285dependencies need to be retrieved using a fetcher. `rustPlatform` 286provides the `fetchCargoTarball` fetcher, which vendors all 287dependencies of a crate. For example, given a source path `src` 288containing `Cargo.toml` and `Cargo.lock`, `fetchCargoTarball` 289can be used as follows: 290 291```nix 292cargoDeps = rustPlatform.fetchCargoTarball { 293 inherit src; 294 hash = "sha256-BoHIN/519Top1NUBjpB/oEMqi86Omt3zTQcXFWqrek0="; 295}; 296``` 297 298The `src` attribute is required, as well as a hash specified through 299one of the `sha256` or `hash` attributes. The following optional 300attributes can also be used: 301 302* `name`: the name that is used for the dependencies tarball. If 303 `name` is not specified, then the name `cargo-deps` will be used. 304* `sourceRoot`: when the `Cargo.lock`/`Cargo.toml` are in a 305 subdirectory, `sourceRoot` specifies the relative path to these 306 files. 307* `patches`: patches to apply before vendoring. This is useful when 308 the `Cargo.lock`/`Cargo.toml` files need to be patched before 309 vendoring. 310 311### Hooks 312 313`rustPlatform` provides the following hooks to automate Cargo builds: 314 315* `cargoSetupHook`: configure Cargo to use depenencies vendored 316 through `fetchCargoTarball`. This hook uses the `cargoDeps` 317 environment variable to find the vendored dependencies. If a project 318 already vendors its dependencies, the variable `cargoVendorDir` can 319 be used instead. When the `Cargo.toml`/`Cargo.lock` files are not in 320 `sourceRoot`, then the optional `cargoRoot` is used to specify the 321 Cargo root directory relative to `sourceRoot`. 322* `cargoBuildHook`: use Cargo to build a crate. If the crate to be 323 built is a crate in e.g. a Cargo workspace, the relative path to the 324 crate to build can be set through the optional `buildAndTestSubdir` 325 environment variable. Additional Cargo build flags can be passed 326 through `cargoBuildFlags`. 327* `maturinBuildHook`: use [Maturin](https://github.com/PyO3/maturin) 328 to build a Python wheel. Similar to `cargoBuildHook`, the optional 329 variable `buildAndTestSubdir` can be used to build a crate in a 330 Cargo workspace. Additional maturin flags can be passed through 331 `maturinBuildFlags`. 332* `cargoCheckHook`: run tests using Cargo. The build type for checks 333 can be set using `cargoCheckType`. Additional flags can be passed to 334 the tests using `checkFlags` and `checkFlagsArray`. By default, 335 tests are run in parallel. This can be disabled by setting 336 `dontUseCargoParallelTests`. 337* `cargoInstallHook`: install binaries and static/shared libraries 338 that were built using `cargoBuildHook`. 339 340### Examples 341 342#### Python package using `setuptools-rust` 343 344For Python packages using `setuptools-rust`, you can use 345`fetchCargoTarball` and `cargoSetupHook` to retrieve and set up Cargo 346dependencies. The build itself is then performed by 347`buildPythonPackage`. 348 349The following example outlines how the `tokenizers` Python package is 350built. Since the Python package is in the `source/bindings/python` 351directory of the *tokenizers* project's source archive, we use 352`sourceRoot` to point the tooling to this directory: 353 354```nix 355{ fetchFromGitHub 356, buildPythonPackage 357, rustPlatform 358, setuptools-rust 359}: 360 361buildPythonPackage rec { 362 pname = "tokenizers"; 363 version = "0.10.0"; 364 365 src = fetchFromGitHub { 366 owner = "huggingface"; 367 repo = pname; 368 rev = "python-v${version}"; 369 hash = "sha256-rQ2hRV52naEf6PvRsWVCTN7B1oXAQGmnpJw4iIdhamw="; 370 }; 371 372 cargoDeps = rustPlatform.fetchCargoTarball { 373 inherit src sourceRoot; 374 name = "${pname}-${version}"; 375 hash = "sha256-BoHIN/519Top1NUBjpB/oEMqi86Omt3zTQcXFWqrek0="; 376 }; 377 378 sourceRoot = "source/bindings/python"; 379 380 nativeBuildInputs = [ setuptools-rust ] ++ (with rustPlatform; [ 381 cargoSetupHook 382 rust.cargo 383 rust.rustc 384 ]); 385 386 # ... 387} 388``` 389 390In some projects, the Rust crate is not in the main Python source 391directory. In such cases, the `cargoRoot` attribute can be used to 392specify the crate's directory relative to `sourceRoot`. In the 393following example, the crate is in `src/rust`, as specified in the 394`cargoRoot` attribute. Note that we also need to specify the correct 395path for `fetchCargoTarball`. 396 397```nix 398 399{ buildPythonPackage 400, fetchPypi 401, rustPlatform 402, setuptools-rust 403, openssl 404}: 405 406buildPythonPackage rec { 407 pname = "cryptography"; 408 version = "3.4.2"; # Also update the hash in vectors.nix 409 410 src = fetchPypi { 411 inherit pname version; 412 sha256 = "1i1mx5y9hkyfi9jrrkcw804hmkcglxi6rmf7vin7jfnbr2bf4q64"; 413 }; 414 415 cargoDeps = rustPlatform.fetchCargoTarball { 416 inherit src; 417 sourceRoot = "${pname}-${version}/${cargoRoot}"; 418 name = "${pname}-${version}"; 419 hash = "sha256-PS562W4L1NimqDV2H0jl5vYhL08H9est/pbIxSdYVfo="; 420 }; 421 422 cargoRoot = "src/rust"; 423 424 # ... 425} 426``` 427 428#### Python package using `maturin` 429 430Python packages that use [Maturin](https://github.com/PyO3/maturin) 431can be built with `fetchCargoTarball`, `cargoSetupHook`, and 432`maturinBuildHook`. For example, the following (partial) derivation 433builds the `retworkx` Python package. `fetchCargoTarball` and 434`cargoSetupHook` are used to fetch and set up the crate dependencies. 435`maturinBuildHook` is used to perform the build. 436 437```nix 438{ lib 439, buildPythonPackage 440, rustPlatform 441, fetchFromGitHub 442}: 443 444buildPythonPackage rec { 445 pname = "retworkx"; 446 version = "0.6.0"; 447 448 src = fetchFromGitHub { 449 owner = "Qiskit"; 450 repo = "retworkx"; 451 rev = version; 452 sha256 = "11n30ldg3y3y6qxg3hbj837pnbwjkqw3nxq6frds647mmmprrd20"; 453 }; 454 455 cargoDeps = rustPlatform.fetchCargoTarball { 456 inherit src; 457 name = "${pname}-${version}"; 458 hash = "sha256-heOBK8qi2nuc/Ib+I/vLzZ1fUUD/G/KTw9d7M4Hz5O0="; 459 }; 460 461 format = "pyproject"; 462 463 nativeBuildInputs = with rustPlatform; [ cargoSetupHook maturinBuildHook ]; 464 465 # ... 466} 467``` 468 469## Compiling Rust crates using Nix instead of Cargo 470 471### Simple operation 472 473When run, `cargo build` produces a file called `Cargo.lock`, 474containing pinned versions of all dependencies. Nixpkgs contains a 475tool called `carnix` (`nix-env -iA nixos.carnix`), which can be used 476to turn a `Cargo.lock` into a Nix expression. 477 478That Nix expression calls `rustc` directly (hence bypassing Cargo), 479and can be used to compile a crate and all its dependencies. Here is 480an example for a minimal `hello` crate: 481 482 483 $ cargo new hello 484 $ cd hello 485 $ cargo build 486 Compiling hello v0.1.0 (file:///tmp/hello) 487 Finished dev [unoptimized + debuginfo] target(s) in 0.20 secs 488 $ carnix -o hello.nix --src ./. Cargo.lock --standalone 489 $ nix-build hello.nix -A hello_0_1_0 490 491Now, the file produced by the call to `carnix`, called `hello.nix`, looks like: 492 493```nix 494# Generated by carnix 0.6.5: carnix -o hello.nix --src ./. Cargo.lock --standalone 495{ stdenv, buildRustCrate, fetchgit }: 496let kernel = stdenv.buildPlatform.parsed.kernel.name; 497 # ... (content skipped) 498in 499rec { 500 hello = f: hello_0_1_0 { features = hello_0_1_0_features { hello_0_1_0 = f; }; }; 501 hello_0_1_0_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate { 502 crateName = "hello"; 503 version = "0.1.0"; 504 authors = [ "pe@pijul.org <pe@pijul.org>" ]; 505 src = ./.; 506 inherit dependencies buildDependencies features; 507 }; 508 hello_0_1_0 = { features?(hello_0_1_0_features {}) }: hello_0_1_0_ {}; 509 hello_0_1_0_features = f: updateFeatures f (rec { 510 hello_0_1_0.default = (f.hello_0_1_0.default or true); 511 }) [ ]; 512} 513``` 514 515In particular, note that the argument given as `--src` is copied 516verbatim to the source. If we look at a more complicated 517dependencies, for instance by adding a single line `libc="*"` to our 518`Cargo.toml`, we first need to run `cargo build` to update the 519`Cargo.lock`. Then, `carnix` needs to be run again, and produces the 520following nix file: 521 522```nix 523# Generated by carnix 0.6.5: carnix -o hello.nix --src ./. Cargo.lock --standalone 524{ stdenv, buildRustCrate, fetchgit }: 525let kernel = stdenv.buildPlatform.parsed.kernel.name; 526 # ... (content skipped) 527in 528rec { 529 hello = f: hello_0_1_0 { features = hello_0_1_0_features { hello_0_1_0 = f; }; }; 530 hello_0_1_0_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate { 531 crateName = "hello"; 532 version = "0.1.0"; 533 authors = [ "pe@pijul.org <pe@pijul.org>" ]; 534 src = ./.; 535 inherit dependencies buildDependencies features; 536 }; 537 libc_0_2_36_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate { 538 crateName = "libc"; 539 version = "0.2.36"; 540 authors = [ "The Rust Project Developers" ]; 541 sha256 = "01633h4yfqm0s302fm0dlba469bx8y6cs4nqc8bqrmjqxfxn515l"; 542 inherit dependencies buildDependencies features; 543 }; 544 hello_0_1_0 = { features?(hello_0_1_0_features {}) }: hello_0_1_0_ { 545 dependencies = mapFeatures features ([ libc_0_2_36 ]); 546 }; 547 hello_0_1_0_features = f: updateFeatures f (rec { 548 hello_0_1_0.default = (f.hello_0_1_0.default or true); 549 libc_0_2_36.default = true; 550 }) [ libc_0_2_36_features ]; 551 libc_0_2_36 = { features?(libc_0_2_36_features {}) }: libc_0_2_36_ { 552 features = mkFeatures (features.libc_0_2_36 or {}); 553 }; 554 libc_0_2_36_features = f: updateFeatures f (rec { 555 libc_0_2_36.default = (f.libc_0_2_36.default or true); 556 libc_0_2_36.use_std = 557 (f.libc_0_2_36.use_std or false) || 558 (f.libc_0_2_36.default or false) || 559 (libc_0_2_36.default or false); 560 }) []; 561} 562``` 563 564Here, the `libc` crate has no `src` attribute, so `buildRustCrate` 565will fetch it from [crates.io](https://crates.io). A `sha256` 566attribute is still needed for Nix purity. 567 568### Handling external dependencies 569 570Some crates require external libraries. For crates from 571[crates.io](https://crates.io), such libraries can be specified in 572`defaultCrateOverrides` package in nixpkgs itself. 573 574Starting from that file, one can add more overrides, to add features 575or build inputs by overriding the hello crate in a seperate file. 576 577```nix 578with import <nixpkgs> {}; 579((import ./hello.nix).hello {}).override { 580 crateOverrides = defaultCrateOverrides // { 581 hello = attrs: { buildInputs = [ openssl ]; }; 582 }; 583} 584``` 585 586Here, `crateOverrides` is expected to be a attribute set, where the 587key is the crate name without version number and the value a function. 588The function gets all attributes passed to `buildRustCrate` as first 589argument and returns a set that contains all attribute that should be 590overwritten. 591 592For more complicated cases, such as when parts of the crate's 593derivation depend on the crate's version, the `attrs` argument of 594the override above can be read, as in the following example, which 595patches the derivation: 596 597```nix 598with import <nixpkgs> {}; 599((import ./hello.nix).hello {}).override { 600 crateOverrides = defaultCrateOverrides // { 601 hello = attrs: lib.optionalAttrs (lib.versionAtLeast attrs.version "1.0") { 602 postPatch = '' 603 substituteInPlace lib/zoneinfo.rs \ 604 --replace "/usr/share/zoneinfo" "${tzdata}/share/zoneinfo" 605 ''; 606 }; 607 }; 608} 609``` 610 611Another situation is when we want to override a nested 612dependency. This actually works in the exact same way, since the 613`crateOverrides` parameter is forwarded to the crate's 614dependencies. For instance, to override the build inputs for crate 615`libc` in the example above, where `libc` is a dependency of the main 616crate, we could do: 617 618```nix 619with import <nixpkgs> {}; 620((import hello.nix).hello {}).override { 621 crateOverrides = defaultCrateOverrides // { 622 libc = attrs: { buildInputs = []; }; 623 }; 624} 625``` 626 627### Options and phases configuration 628 629Actually, the overrides introduced in the previous section are more 630general. A number of other parameters can be overridden: 631 632- The version of rustc used to compile the crate: 633 634 ```nix 635 (hello {}).override { rust = pkgs.rust; }; 636 ``` 637 638- Whether to build in release mode or debug mode (release mode by 639 default): 640 641 ```nix 642 (hello {}).override { release = false; }; 643 ``` 644 645- Whether to print the commands sent to rustc when building 646 (equivalent to `--verbose` in cargo: 647 648 ```nix 649 (hello {}).override { verbose = false; }; 650 ``` 651 652- Extra arguments to be passed to `rustc`: 653 654 ```nix 655 (hello {}).override { extraRustcOpts = "-Z debuginfo=2"; }; 656 ``` 657 658- Phases, just like in any other derivation, can be specified using 659 the following attributes: `preUnpack`, `postUnpack`, `prePatch`, 660 `patches`, `postPatch`, `preConfigure` (in the case of a Rust crate, 661 this is run before calling the "build" script), `postConfigure` 662 (after the "build" script),`preBuild`, `postBuild`, `preInstall` and 663 `postInstall`. As an example, here is how to create a new module 664 before running the build script: 665 666 ```nix 667 (hello {}).override { 668 preConfigure = '' 669 echo "pub const PATH=\"${hi.out}\";" >> src/path.rs" 670 ''; 671 }; 672 ``` 673 674### Features 675 676One can also supply features switches. For example, if we want to 677compile `diesel_cli` only with the `postgres` feature, and no default 678features, we would write: 679 680```nix 681(callPackage ./diesel.nix {}).diesel { 682 default = false; 683 postgres = true; 684} 685``` 686 687Where `diesel.nix` is the file generated by Carnix, as explained above. 688 689 690## Setting Up `nix-shell` 691Oftentimes you want to develop code from within `nix-shell`. Unfortunately 692`buildRustCrate` does not support common `nix-shell` operations directly 693(see [this issue](https://github.com/NixOS/nixpkgs/issues/37945)) 694so we will use `stdenv.mkDerivation` instead. 695 696Using the example `hello` project above, we want to do the following: 697- Have access to `cargo` and `rustc` 698- Have the `openssl` library available to a crate through it's _normal_ 699 compilation mechanism (`pkg-config`). 700 701A typical `shell.nix` might look like: 702 703```nix 704with import <nixpkgs> {}; 705 706stdenv.mkDerivation { 707 name = "rust-env"; 708 nativeBuildInputs = [ 709 rustc cargo 710 711 # Example Build-time Additional Dependencies 712 pkg-config 713 ]; 714 buildInputs = [ 715 # Example Run-time Additional Dependencies 716 openssl 717 ]; 718 719 # Set Environment Variables 720 RUST_BACKTRACE = 1; 721} 722``` 723 724You should now be able to run the following: 725```ShellSesssion 726$ nix-shell --pure 727$ cargo build 728$ cargo test 729``` 730 731### Controlling Rust Version Inside `nix-shell` 732To control your rust version (i.e. use nightly) from within `shell.nix` (or 733other nix expressions) you can use the following `shell.nix` 734 735```nix 736# Latest Nightly 737with import <nixpkgs> {}; 738let src = fetchFromGitHub { 739 owner = "mozilla"; 740 repo = "nixpkgs-mozilla"; 741 # commit from: 2019-05-15 742 rev = "9f35c4b09fd44a77227e79ff0c1b4b6a69dff533"; 743 sha256 = "18h0nvh55b5an4gmlgfbvwbyqj91bklf1zymis6lbdh75571qaz0"; 744 }; 745in 746with import "${src.out}/rust-overlay.nix" pkgs pkgs; 747stdenv.mkDerivation { 748 name = "rust-env"; 749 buildInputs = [ 750 # Note: to use stable, just replace `nightly` with `stable` 751 latest.rustChannels.nightly.rust 752 753 # Add some extra dependencies from `pkgs` 754 pkg-config openssl 755 ]; 756 757 # Set Environment Variables 758 RUST_BACKTRACE = 1; 759} 760``` 761 762Now run: 763```ShellSession 764$ rustc --version 765rustc 1.26.0-nightly (188e693b3 2018-03-26) 766``` 767 768To see that you are using nightly. 769 770 771## Using the Rust nightlies overlay 772 773Mozilla provides an overlay for nixpkgs to bring a nightly version of Rust into scope. 774This overlay can _also_ be used to install recent unstable or stable versions 775of Rust, if desired. 776 777### Rust overlay installation 778 779You can use this overlay by either changing your local nixpkgs configuration, 780or by adding the overlay declaratively in a nix expression, e.g. in `configuration.nix`. 781For more information see [#sec-overlays-install](the manual on installing overlays). 782 783#### Imperative rust overlay installation 784 785Clone [nixpkgs-mozilla](https://github.com/mozilla/nixpkgs-mozilla), 786and create a symbolic link to the file 787[rust-overlay.nix](https://github.com/mozilla/nixpkgs-mozilla/blob/master/rust-overlay.nix) 788in the `~/.config/nixpkgs/overlays` directory. 789 790 $ git clone https://github.com/mozilla/nixpkgs-mozilla.git 791 $ mkdir -p ~/.config/nixpkgs/overlays 792 $ ln -s $(pwd)/nixpkgs-mozilla/rust-overlay.nix ~/.config/nixpkgs/overlays/rust-overlay.nix 793 794### Declarative rust overlay installation 795 796Add the following to your `configuration.nix`, `home-configuration.nix`, `shell.nix`, or similar: 797 798```nix 799{ pkgs ? import <nixpkgs> { 800 overlays = [ 801 (import (builtins.fetchTarball https://github.com/mozilla/nixpkgs-mozilla/archive/master.tar.gz)) 802 # Further overlays go here 803 ]; 804 }; 805}; 806``` 807 808Note that this will fetch the latest overlay version when rebuilding your system. 809 810### Rust overlay usage 811 812The overlay contains attribute sets corresponding to different versions of the rust toolchain, such as: 813 814* `latest.rustChannels.stable` 815* `latest.rustChannels.nightly` 816* a function `rustChannelOf`, called as `(rustChannelOf { date = "2018-04-11"; channel = "nightly"; })`, or... 817* `(nixpkgs.rustChannelOf { rustToolchain = ./rust-toolchain; })` if you have a local `rust-toolchain` file (see https://github.com/mozilla/nixpkgs-mozilla#using-in-nix-expressions for an example) 818 819Each of these contain packages such as `rust`, which contains your usual rust development tools with the respective toolchain chosen. 820For example, you might want to add `latest.rustChannels.stable.rust` to the list of packages in your configuration. 821 822Imperatively, the latest stable version can be installed with the following command: 823 824 $ nix-env -Ai nixpkgs.latest.rustChannels.stable.rust 825 826Or using the attribute with nix-shell: 827 828 $ nix-shell -p nixpkgs.latest.rustChannels.stable.rust 829 830Substitute the `nixpkgs` prefix with `nixos` on NixOS. 831To install the beta or nightly channel, "stable" should be substituted by 832"nightly" or "beta", or 833use the function provided by this overlay to pull a version based on a 834build date. 835 836The overlay automatically updates itself as it uses the same source as 837[rustup](https://www.rustup.rs/).