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/).