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 [community maintained Rust toolchains](#using-community-maintained-rust-toolchains).
17
18## `buildRustPackage`: Compiling Rust applications with Cargo {#compiling-rust-applications-with-cargo}
19
20Rust applications are packaged by using the `buildRustPackage` helper from `rustPlatform`:
21
22```nix
23{ lib, fetchFromGitHub, 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 hash = "sha256-+s5RBC3XSgb8omTbUNLywZnP6jSxZBKSS1BmXOjRF8M=";
34 };
35
36 cargoHash = "sha256-jtBw4ahSl88L0iuCXxQgZVm1EcboWRJMNtjxLVTtzts=";
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 = [];
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
53Exception: If the application has cargo `git` dependencies, the `cargoHash`/`cargoSha256`
54approach will not work, and you will need to copy the `Cargo.lock` file of the application
55to nixpkgs and continue with the next section for specifying the options of the`cargoLock`
56section.
57
58```nix
59 cargoHash = "sha256-l1vL2ZdtDRxSGvP0X/l3nMw8+6WF67KPutJEzUROjg8=";
60```
61
62Both types of hashes are permitted when contributing to nixpkgs. The
63Cargo hash is obtained by inserting a fake checksum into the
64expression and building the package once. The correct checksum can
65then be taken from the failed build. A fake hash can be used for
66`cargoSha256` as follows:
67
68```nix
69 cargoSha256 = lib.fakeSha256;
70```
71
72For `cargoHash` you can use:
73
74```nix
75 cargoHash = lib.fakeHash;
76```
77
78Per the instructions in the [Cargo Book](https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html)
79best practices guide, Rust applications should always commit the `Cargo.lock`
80file in git to ensure a reproducible build. However, a few packages do not, and
81Nix depends on this file, so if it is missing you can use `cargoPatches` to
82apply it in the `patchPhase`. Consider sending a PR upstream with a note to the
83maintainer describing why it's important to include in the application.
84
85The fetcher will verify that the `Cargo.lock` file is in sync with the `src`
86attribute, and fail the build if not. It will also will compress the vendor
87directory into a tar.gz archive.
88
89The tarball with vendored dependencies contains a directory with the
90package's `name`, which is normally composed of `pname` and
91`version`. This means that the vendored dependencies hash
92(`cargoSha256`/`cargoHash`) is dependent on the package name and
93version. The `cargoDepsName` attribute can be used to use another name
94for the directory of vendored dependencies. For example, the hash can
95be made invariant to the version by setting `cargoDepsName` to
96`pname`:
97
98```nix
99rustPlatform.buildRustPackage rec {
100 pname = "broot";
101 version = "1.2.0";
102
103 src = fetchCrate {
104 inherit pname version;
105 hash = "sha256-aDQA4A5mScX9or3Lyiv/5GyAehidnpKKE0grhbP1Ctc=";
106 };
107
108 cargoHash = "sha256-tbrTbutUs5aPSV+yE0IBUZAAytgmZV7Eqxia7g+9zRs=";
109 cargoDepsName = pname;
110
111 # ...
112}
113```
114
115### Importing a `Cargo.lock` file {#importing-a-cargo.lock-file}
116
117Using `cargoSha256` or `cargoHash` is tedious when using
118`buildRustPackage` within a project, since it requires that the hash
119is updated after every change to `Cargo.lock`. Therefore,
120`buildRustPackage` also supports vendoring dependencies directly from
121a `Cargo.lock` file using the `cargoLock` argument. For example:
122
123```nix
124rustPlatform.buildRustPackage {
125 pname = "myproject";
126 version = "1.0.0";
127
128 cargoLock = {
129 lockFile = ./Cargo.lock;
130 };
131
132 # ...
133}
134```
135
136This will retrieve the dependencies using fixed-output derivations from
137the specified lockfile.
138
139One caveat is that `Cargo.lock` cannot be patched in the `patchPhase`
140because it runs after the dependencies have already been fetched. If
141you need to patch or generate the lockfile you can alternatively set
142`cargoLock.lockFileContents` to a string of its contents:
143
144```nix
145rustPlatform.buildRustPackage {
146 pname = "myproject";
147 version = "1.0.0";
148
149 cargoLock = let
150 fixupLockFile = path: f (builtins.readFile path);
151 in {
152 lockFileContents = fixupLockFile ./Cargo.lock;
153 };
154
155 # ...
156}
157```
158
159Note that setting `cargoLock.lockFile` or `cargoLock.lockFileContents`
160doesn't add a `Cargo.lock` to your `src`, and a `Cargo.lock` is still
161required to build a rust package. A simple fix is to use:
162
163```nix
164postPatch = ''
165 ln -s ${./Cargo.lock} Cargo.lock
166'';
167```
168
169The output hash of each dependency that uses a git source must be
170specified in the `outputHashes` attribute. For example:
171
172```nix
173rustPlatform.buildRustPackage rec {
174 pname = "myproject";
175 version = "1.0.0";
176
177 cargoLock = {
178 lockFile = ./Cargo.lock;
179 outputHashes = {
180 "finalfusion-0.14.0" = "17f4bsdzpcshwh74w5z119xjy2if6l2wgyjy56v621skr2r8y904";
181 };
182 };
183
184 # ...
185}
186```
187
188If you do not specify an output hash for a git dependency, building
189the package will fail and inform you of which crate needs to be
190added. To find the correct hash, you can first use `lib.fakeSha256` or
191`lib.fakeHash` as a stub hash. Building the package (and thus the
192vendored dependencies) will then inform you of the correct hash.
193
194For usage outside nixpkgs, `allowBuiltinFetchGit` could be used to
195avoid having to specify `outputHashes`. For example:
196
197```nix
198rustPlatform.buildRustPackage rec {
199 pname = "myproject";
200 version = "1.0.0";
201
202 cargoLock = {
203 lockFile = ./Cargo.lock;
204 allowBuiltinFetchGit = true;
205 };
206
207 # ...
208}
209```
210
211### Cargo features {#cargo-features}
212
213You can disable default features using `buildNoDefaultFeatures`, and
214extra features can be added with `buildFeatures`.
215
216If you want to use different features for check phase, you can use
217`checkNoDefaultFeatures` and `checkFeatures`. They are only passed to
218`cargo test` and not `cargo build`. If left unset, they default to
219`buildNoDefaultFeatures` and `buildFeatures`.
220
221For example:
222
223```nix
224rustPlatform.buildRustPackage rec {
225 pname = "myproject";
226 version = "1.0.0";
227
228 buildNoDefaultFeatures = true;
229 buildFeatures = [ "color" "net" ];
230
231 # disable network features in tests
232 checkFeatures = [ "color" ];
233
234 # ...
235}
236```
237
238### Cross compilation {#cross-compilation}
239
240By default, Rust packages are compiled for the host platform, just like any
241other package is. The `--target` passed to rust tools is computed from this.
242By default, it takes the `stdenv.hostPlatform.config` and replaces components
243where they are known to differ. But there are ways to customize the argument:
244
245 - To choose a different target by name, define
246 `stdenv.hostPlatform.rustc.config` as that name (a string), and that
247 name will be used instead.
248
249 For example:
250
251 ```nix
252 import <nixpkgs> {
253 crossSystem = (import <nixpkgs/lib>).systems.examples.armhf-embedded // {
254 rustc.config = "thumbv7em-none-eabi";
255 };
256 }
257 ```
258
259 will result in:
260
261 ```shell
262 --target thumbv7em-none-eabi
263 ```
264
265 - To pass a completely custom target, define
266 `stdenv.hostPlatform.rustc.config` with its name, and
267 `stdenv.hostPlatform.rustc.platform` with the value. The value will be
268 serialized to JSON in a file called
269 `${stdenv.hostPlatform.rustc.config}.json`, and the path of that file
270 will be used instead.
271
272 For example:
273
274 ```nix
275 import <nixpkgs> {
276 crossSystem = (import <nixpkgs/lib>).systems.examples.armhf-embedded // {
277 rustc.config = "thumb-crazy";
278 rustc.platform = { foo = ""; bar = ""; };
279 };
280 }
281 ```
282
283 will result in:
284
285 ```shell
286 --target /nix/store/asdfasdfsadf-thumb-crazy.json # contains {"foo":"","bar":""}
287 ```
288
289Note that currently custom targets aren't compiled with `std`, so `cargo test`
290will fail. This can be ignored by adding `doCheck = false;` to your derivation.
291
292### Running package tests {#running-package-tests}
293
294When using `buildRustPackage`, the `checkPhase` is enabled by default and runs
295`cargo test` on the package to build. To make sure that we don't compile the
296sources twice and to actually test the artifacts that will be used at runtime,
297the tests will be ran in the `release` mode by default.
298
299However, in some cases the test-suite of a package doesn't work properly in the
300`release` mode. For these situations, the mode for `checkPhase` can be changed like
301so:
302
303```nix
304rustPlatform.buildRustPackage {
305 /* ... */
306 checkType = "debug";
307}
308```
309
310Please note that the code will be compiled twice here: once in `release` mode
311for the `buildPhase`, and again in `debug` mode for the `checkPhase`.
312
313Test flags, e.g., `--package foo`, can be passed to `cargo test` via the
314`cargoTestFlags` attribute.
315
316Another attribute, called `checkFlags`, is used to pass arguments to the test
317binary itself, as stated
318[here](https://doc.rust-lang.org/cargo/commands/cargo-test.html).
319
320#### Tests relying on the structure of the `target/` directory {#tests-relying-on-the-structure-of-the-target-directory}
321
322Some tests may rely on the structure of the `target/` directory. Those tests
323are likely to fail because we use `cargo --target` during the build. This means that
324the artifacts
325[are stored in `target/<architecture>/release/`](https://doc.rust-lang.org/cargo/guide/build-cache.html),
326rather than in `target/release/`.
327
328This can only be worked around by patching the affected tests accordingly.
329
330#### Disabling package-tests {#disabling-package-tests}
331
332In some instances, it may be necessary to disable testing altogether (with `doCheck = false;`):
333
334* If no tests exist -- the `checkPhase` should be explicitly disabled to skip
335 unnecessary build steps to speed up the build.
336* If tests are highly impure (e.g. due to network usage).
337
338There will obviously be some corner-cases not listed above where it's sensible to disable tests.
339The above are just guidelines, and exceptions may be granted on a case-by-case basis.
340
341However, please check if it's possible to disable a problematic subset of the
342test suite and leave a comment explaining your reasoning.
343
344This can be achieved with `--skip` in `checkFlags`:
345
346```nix
347rustPlatform.buildRustPackage {
348 /* ... */
349 checkFlags = [
350 # reason for disabling test
351 "--skip=example::tests:example_test"
352 ];
353}
354```
355
356#### Using `cargo-nextest` {#using-cargo-nextest}
357
358Tests can be run with [cargo-nextest](https://github.com/nextest-rs/nextest)
359by setting `useNextest = true`. The same options still apply, but nextest
360accepts a different set of arguments and the settings might need to be
361adapted to be compatible with cargo-nextest.
362
363```nix
364rustPlatform.buildRustPackage {
365 /* ... */
366 useNextest = true;
367}
368```
369
370#### Setting `test-threads` {#setting-test-threads}
371
372`buildRustPackage` will use parallel test threads by default,
373sometimes it may be necessary to disable this so the tests run consecutively.
374
375```nix
376rustPlatform.buildRustPackage {
377 /* ... */
378 dontUseCargoParallelTests = true;
379}
380```
381
382### Building a package in `debug` mode {#building-a-package-in-debug-mode}
383
384By default, `buildRustPackage` will use `release` mode for builds. If a package
385should be built in `debug` mode, it can be configured like so:
386
387```nix
388rustPlatform.buildRustPackage {
389 /* ... */
390 buildType = "debug";
391}
392```
393
394In this scenario, the `checkPhase` will be ran in `debug` mode as well.
395
396### Custom `build`/`install`-procedures {#custom-buildinstall-procedures}
397
398Some packages may use custom scripts for building/installing, e.g. with a `Makefile`.
399In these cases, it's recommended to override the `buildPhase`/`installPhase`/`checkPhase`.
400
401Otherwise, some steps may fail because of the modified directory structure of `target/`.
402
403### Building a crate with an absent or out-of-date Cargo.lock file {#building-a-crate-with-an-absent-or-out-of-date-cargo.lock-file}
404
405`buildRustPackage` needs a `Cargo.lock` file to get all dependencies in the
406source code in a reproducible way. If it is missing or out-of-date one can use
407the `cargoPatches` attribute to update or add it.
408
409```nix
410rustPlatform.buildRustPackage rec {
411 (...)
412 cargoPatches = [
413 # a patch file to add/update Cargo.lock in the source code
414 ./add-Cargo.lock.patch
415 ];
416}
417```
418
419### Compiling non-Rust packages that include Rust code {#compiling-non-rust-packages-that-include-rust-code}
420
421Several non-Rust packages incorporate Rust code for performance- or
422security-sensitive parts. `rustPlatform` exposes several functions and
423hooks that can be used to integrate Cargo in non-Rust packages.
424
425#### Vendoring of dependencies {#vendoring-of-dependencies}
426
427Since network access is not allowed in sandboxed builds, Rust crate
428dependencies need to be retrieved using a fetcher. `rustPlatform`
429provides the `fetchCargoTarball` fetcher, which vendors all
430dependencies of a crate. For example, given a source path `src`
431containing `Cargo.toml` and `Cargo.lock`, `fetchCargoTarball`
432can be used as follows:
433
434```nix
435cargoDeps = rustPlatform.fetchCargoTarball {
436 inherit src;
437 hash = "sha256-BoHIN/519Top1NUBjpB/oEMqi86Omt3zTQcXFWqrek0=";
438};
439```
440
441The `src` attribute is required, as well as a hash specified through
442one of the `hash` attribute. The following optional attributes can
443also be used:
444
445* `name`: the name that is used for the dependencies tarball. If
446 `name` is not specified, then the name `cargo-deps` will be used.
447* `sourceRoot`: when the `Cargo.lock`/`Cargo.toml` are in a
448 subdirectory, `sourceRoot` specifies the relative path to these
449 files.
450* `patches`: patches to apply before vendoring. This is useful when
451 the `Cargo.lock`/`Cargo.toml` files need to be patched before
452 vendoring.
453
454If a `Cargo.lock` file is available, you can alternatively use the
455`importCargoLock` function. In contrast to `fetchCargoTarball`, this
456function does not require a hash (unless git dependencies are used)
457and fetches every dependency as a separate fixed-output derivation.
458`importCargoLock` can be used as follows:
459
460```
461cargoDeps = rustPlatform.importCargoLock {
462 lockFile = ./Cargo.lock;
463};
464```
465
466If the `Cargo.lock` file includes git dependencies, then their output
467hashes need to be specified since they are not available through the
468lock file. For example:
469
470```
471cargoDeps = rustPlatform.importCargoLock {
472 lockFile = ./Cargo.lock;
473 outputHashes = {
474 "rand-0.8.3" = "0ya2hia3cn31qa8894s3av2s8j5bjwb6yq92k0jsnlx7jid0jwqa";
475 };
476};
477```
478
479If you do not specify an output hash for a git dependency, building
480`cargoDeps` will fail and inform you of which crate needs to be
481added. To find the correct hash, you can first use `lib.fakeSha256` or
482`lib.fakeHash` as a stub hash. Building `cargoDeps` will then inform
483you of the correct hash.
484
485#### Hooks {#hooks}
486
487`rustPlatform` provides the following hooks to automate Cargo builds:
488
489* `cargoSetupHook`: configure Cargo to use dependencies vendored
490 through `fetchCargoTarball`. This hook uses the `cargoDeps`
491 environment variable to find the vendored dependencies. If a project
492 already vendors its dependencies, the variable `cargoVendorDir` can
493 be used instead. When the `Cargo.toml`/`Cargo.lock` files are not in
494 `sourceRoot`, then the optional `cargoRoot` is used to specify the
495 Cargo root directory relative to `sourceRoot`.
496* `cargoBuildHook`: use Cargo to build a crate. If the crate to be
497 built is a crate in e.g. a Cargo workspace, the relative path to the
498 crate to build can be set through the optional `buildAndTestSubdir`
499 environment variable. Features can be specified with
500 `cargoBuildNoDefaultFeatures` and `cargoBuildFeatures`. Additional
501 Cargo build flags can be passed through `cargoBuildFlags`.
502* `maturinBuildHook`: use [Maturin](https://github.com/PyO3/maturin)
503 to build a Python wheel. Similar to `cargoBuildHook`, the optional
504 variable `buildAndTestSubdir` can be used to build a crate in a
505 Cargo workspace. Additional Maturin flags can be passed through
506 `maturinBuildFlags`.
507* `cargoCheckHook`: run tests using Cargo. The build type for checks
508 can be set using `cargoCheckType`. Features can be specified with
509 `cargoCheckNoDefaultFeatures` and `cargoCheckFeatures`. Additional
510 flags can be passed to the tests using `checkFlags` and
511 `checkFlagsArray`. By default, tests are run in parallel. This can
512 be disabled by setting `dontUseCargoParallelTests`.
513* `cargoNextestHook`: run tests using
514 [cargo-nextest](https://github.com/nextest-rs/nextest). The same
515 options for `cargoCheckHook` also applies to `cargoNextestHook`.
516* `cargoInstallHook`: install binaries and static/shared libraries
517 that were built using `cargoBuildHook`.
518* `bindgenHook`: for crates which use `bindgen` as a build dependency, lets
519 `bindgen` find `libclang` and `libclang` find the libraries in `buildInputs`.
520
521#### Examples {#examples}
522
523#### Python package using `setuptools-rust` {#python-package-using-setuptools-rust}
524
525For Python packages using `setuptools-rust`, you can use
526`fetchCargoTarball` and `cargoSetupHook` to retrieve and set up Cargo
527dependencies. The build itself is then performed by
528`buildPythonPackage`.
529
530The following example outlines how the `tokenizers` Python package is
531built. Since the Python package is in the `source/bindings/python`
532directory of the `tokenizers` project's source archive, we use
533`sourceRoot` to point the tooling to this directory:
534
535```nix
536{ fetchFromGitHub
537, buildPythonPackage
538, cargo
539, rustPlatform
540, rustc
541, setuptools-rust
542}:
543
544buildPythonPackage rec {
545 pname = "tokenizers";
546 version = "0.10.0";
547
548 src = fetchFromGitHub {
549 owner = "huggingface";
550 repo = pname;
551 rev = "python-v${version}";
552 hash = "sha256-rQ2hRV52naEf6PvRsWVCTN7B1oXAQGmnpJw4iIdhamw=";
553 };
554
555 cargoDeps = rustPlatform.fetchCargoTarball {
556 inherit src sourceRoot;
557 name = "${pname}-${version}";
558 hash = "sha256-miW//pnOmww2i6SOGbkrAIdc/JMDT4FJLqdMFojZeoY=";
559 };
560
561 sourceRoot = "${src.name}/bindings/python";
562
563 nativeBuildInputs = [
564 cargo
565 rustPlatform.cargoSetupHook
566 rustc
567 setuptools-rust
568 ];
569
570 # ...
571}
572```
573
574In some projects, the Rust crate is not in the main Python source
575directory. In such cases, the `cargoRoot` attribute can be used to
576specify the crate's directory relative to `sourceRoot`. In the
577following example, the crate is in `src/rust`, as specified in the
578`cargoRoot` attribute. Note that we also need to specify the correct
579path for `fetchCargoTarball`.
580
581```nix
582
583{ buildPythonPackage
584, fetchPypi
585, rustPlatform
586, setuptools-rust
587, openssl
588}:
589
590buildPythonPackage rec {
591 pname = "cryptography";
592 version = "3.4.2"; # Also update the hash in vectors.nix
593
594 src = fetchPypi {
595 inherit pname version;
596 hash = "sha256-xGDilsjLOnls3MfVbGKnj80KCUCczZxlis5PmHzpNcQ=";
597 };
598
599 cargoDeps = rustPlatform.fetchCargoTarball {
600 inherit src;
601 sourceRoot = "${pname}-${version}/${cargoRoot}";
602 name = "${pname}-${version}";
603 hash = "sha256-PS562W4L1NimqDV2H0jl5vYhL08H9est/pbIxSdYVfo=";
604 };
605
606 cargoRoot = "src/rust";
607
608 # ...
609}
610```
611
612#### Python package using `maturin` {#python-package-using-maturin}
613
614Python packages that use [Maturin](https://github.com/PyO3/maturin)
615can be built with `fetchCargoTarball`, `cargoSetupHook`, and
616`maturinBuildHook`. For example, the following (partial) derivation
617builds the `retworkx` Python package. `fetchCargoTarball` and
618`cargoSetupHook` are used to fetch and set up the crate dependencies.
619`maturinBuildHook` is used to perform the build.
620
621```nix
622{ lib
623, buildPythonPackage
624, rustPlatform
625, fetchFromGitHub
626}:
627
628buildPythonPackage rec {
629 pname = "retworkx";
630 version = "0.6.0";
631
632 src = fetchFromGitHub {
633 owner = "Qiskit";
634 repo = "retworkx";
635 rev = version;
636 hash = "sha256-11n30ldg3y3y6qxg3hbj837pnbwjkqw3nxq6frds647mmmprrd20=";
637 };
638
639 cargoDeps = rustPlatform.fetchCargoTarball {
640 inherit src;
641 name = "${pname}-${version}";
642 hash = "sha256-heOBK8qi2nuc/Ib+I/vLzZ1fUUD/G/KTw9d7M4Hz5O0=";
643 };
644
645 format = "pyproject";
646
647 nativeBuildInputs = with rustPlatform; [ cargoSetupHook maturinBuildHook ];
648
649 # ...
650}
651```
652
653## `buildRustCrate`: Compiling Rust crates using Nix instead of Cargo {#compiling-rust-crates-using-nix-instead-of-cargo}
654
655### Simple operation {#simple-operation}
656
657When run, `cargo build` produces a file called `Cargo.lock`,
658containing pinned versions of all dependencies. Nixpkgs contains a
659tool called `crate2Nix` (`nix-shell -p crate2nix`), which can be
660used to turn a `Cargo.lock` into a Nix expression. That Nix
661expression calls `rustc` directly (hence bypassing Cargo), and can
662be used to compile a crate and all its dependencies.
663
664See [`crate2nix`'s documentation](https://github.com/kolloch/crate2nix#known-restrictions)
665for instructions on how to use it.
666
667### Handling external dependencies {#handling-external-dependencies}
668
669Some crates require external libraries. For crates from
670[crates.io](https://crates.io), such libraries can be specified in
671`defaultCrateOverrides` package in nixpkgs itself.
672
673Starting from that file, one can add more overrides, to add features
674or build inputs by overriding the hello crate in a separate file.
675
676```nix
677with import <nixpkgs> {};
678((import ./hello.nix).hello {}).override {
679 crateOverrides = defaultCrateOverrides // {
680 hello = attrs: { buildInputs = [ openssl ]; };
681 };
682}
683```
684
685Here, `crateOverrides` is expected to be a attribute set, where the
686key is the crate name without version number and the value a function.
687The function gets all attributes passed to `buildRustCrate` as first
688argument and returns a set that contains all attribute that should be
689overwritten.
690
691For more complicated cases, such as when parts of the crate's
692derivation depend on the crate's version, the `attrs` argument of
693the override above can be read, as in the following example, which
694patches the derivation:
695
696```nix
697with import <nixpkgs> {};
698((import ./hello.nix).hello {}).override {
699 crateOverrides = defaultCrateOverrides // {
700 hello = attrs: lib.optionalAttrs (lib.versionAtLeast attrs.version "1.0") {
701 postPatch = ''
702 substituteInPlace lib/zoneinfo.rs \
703 --replace "/usr/share/zoneinfo" "${tzdata}/share/zoneinfo"
704 '';
705 };
706 };
707}
708```
709
710Another situation is when we want to override a nested
711dependency. This actually works in the exact same way, since the
712`crateOverrides` parameter is forwarded to the crate's
713dependencies. For instance, to override the build inputs for crate
714`libc` in the example above, where `libc` is a dependency of the main
715crate, we could do:
716
717```nix
718with import <nixpkgs> {};
719((import hello.nix).hello {}).override {
720 crateOverrides = defaultCrateOverrides // {
721 libc = attrs: { buildInputs = []; };
722 };
723}
724```
725
726### Options and phases configuration {#options-and-phases-configuration}
727
728Actually, the overrides introduced in the previous section are more
729general. A number of other parameters can be overridden:
730
731- The version of `rustc` used to compile the crate:
732
733 ```nix
734 (hello {}).override { rust = pkgs.rust; };
735 ```
736
737- Whether to build in release mode or debug mode (release mode by
738 default):
739
740 ```nix
741 (hello {}).override { release = false; };
742 ```
743
744- Whether to print the commands sent to `rustc` when building
745 (equivalent to `--verbose` in cargo:
746
747 ```nix
748 (hello {}).override { verbose = false; };
749 ```
750
751- Extra arguments to be passed to `rustc`:
752
753 ```nix
754 (hello {}).override { extraRustcOpts = "-Z debuginfo=2"; };
755 ```
756
757- Phases, just like in any other derivation, can be specified using
758 the following attributes: `preUnpack`, `postUnpack`, `prePatch`,
759 `patches`, `postPatch`, `preConfigure` (in the case of a Rust crate,
760 this is run before calling the "build" script), `postConfigure`
761 (after the "build" script),`preBuild`, `postBuild`, `preInstall` and
762 `postInstall`. As an example, here is how to create a new module
763 before running the build script:
764
765 ```nix
766 (hello {}).override {
767 preConfigure = ''
768 echo "pub const PATH=\"${hi.out}\";" >> src/path.rs"
769 '';
770 };
771 ```
772
773### Setting Up `nix-shell` {#setting-up-nix-shell}
774
775Oftentimes you want to develop code from within `nix-shell`. Unfortunately
776`buildRustCrate` does not support common `nix-shell` operations directly
777(see [this issue](https://github.com/NixOS/nixpkgs/issues/37945))
778so we will use `stdenv.mkDerivation` instead.
779
780Using the example `hello` project above, we want to do the following:
781
782- Have access to `cargo` and `rustc`
783- Have the `openssl` library available to a crate through it's _normal_
784 compilation mechanism (`pkg-config`).
785
786A typical `shell.nix` might look like:
787
788```nix
789with import <nixpkgs> {};
790
791stdenv.mkDerivation {
792 name = "rust-env";
793 nativeBuildInputs = [
794 rustc cargo
795
796 # Example Build-time Additional Dependencies
797 pkg-config
798 ];
799 buildInputs = [
800 # Example Run-time Additional Dependencies
801 openssl
802 ];
803
804 # Set Environment Variables
805 RUST_BACKTRACE = 1;
806}
807```
808
809You should now be able to run the following:
810
811```ShellSession
812$ nix-shell --pure
813$ cargo build
814$ cargo test
815```
816
817## Using community maintained Rust toolchains {#using-community-maintained-rust-toolchains}
818
819::: {.note}
820The following projects cannot be used within Nixpkgs since [Import From Derivation](https://nixos.org/manual/nix/unstable/language/import-from-derivation) (IFD) is disallowed in Nixpkgs.
821To package things that require Rust nightly, `RUSTC_BOOTSTRAP = true;` can sometimes be used as a hack.
822:::
823
824There are two community maintained approaches to Rust toolchain management:
825- [oxalica's Rust overlay](https://github.com/oxalica/rust-overlay)
826- [fenix](https://github.com/nix-community/fenix)
827
828Despite their names, both projects provides a similar set of packages and overlays under different APIs.
829
830Oxalica's overlay allows you to select a particular Rust version without you providing a hash or a flake input,
831but comes with a larger git repository than fenix.
832
833Fenix also provides rust-analyzer nightly in addition to the Rust toolchains.
834
835Both oxalica's overlay and fenix better integrate with nix and cache optimizations.
836Because of this and ergonomics, either of those community projects
837should be preferred to the Mozilla's Rust overlay ([nixpkgs-mozilla](https://github.com/mozilla/nixpkgs-mozilla)).
838
839The following documentation demonstrates examples using fenix and oxalica's Rust overlay
840with `nix-shell` and building derivations. More advanced usages like flake usage
841are documented in their own repositories.
842
843### Using Rust nightly with `nix-shell` {#using-rust-nightly-with-nix-shell}
844
845Here is a simple `shell.nix` that provides Rust nightly (default profile) using fenix:
846
847```nix
848with import <nixpkgs> { };
849let
850 fenix = callPackage
851 (fetchFromGitHub {
852 owner = "nix-community";
853 repo = "fenix";
854 # commit from: 2023-03-03
855 rev = "e2ea04982b892263c4d939f1cc3bf60a9c4deaa1";
856 hash = "sha256-AsOim1A8KKtMWIxG+lXh5Q4P2bhOZjoUhFWJ1EuZNNk=";
857 })
858 { };
859in
860mkShell {
861 name = "rust-env";
862 nativeBuildInputs = [
863 # Note: to use stable, just replace `default` with `stable`
864 fenix.default.toolchain
865
866 # Example Build-time Additional Dependencies
867 pkg-config
868 ];
869 buildInputs = [
870 # Example Run-time Additional Dependencies
871 openssl
872 ];
873
874 # Set Environment Variables
875 RUST_BACKTRACE = 1;
876}
877```
878
879Save this to `shell.nix`, then run:
880
881```ShellSession
882$ rustc --version
883rustc 1.69.0-nightly (13471d3b2 2023-03-02)
884```
885
886To see that you are using nightly.
887
888Oxalica's Rust overlay has more complete examples of `shell.nix` (and cross compilation) under its
889[`examples` directory](https://github.com/oxalica/rust-overlay/tree/e53e8853aa7b0688bc270e9e6a681d22e01cf299/examples).
890
891### Using Rust nightly in a derivation with `buildRustPackage` {#using-rust-nightly-in-a-derivation-with-buildrustpackage}
892
893You can also use Rust nightly to build rust packages using `makeRustPlatform`.
894The below snippet demonstrates invoking `buildRustPackage` with a Rust toolchain from oxalica's overlay:
895
896```nix
897with import <nixpkgs>
898{
899 overlays = [
900 (import (fetchTarball "https://github.com/oxalica/rust-overlay/archive/master.tar.gz"))
901 ];
902};
903let
904 rustPlatform = makeRustPlatform {
905 cargo = rust-bin.stable.latest.minimal;
906 rustc = rust-bin.stable.latest.minimal;
907 };
908in
909
910rustPlatform.buildRustPackage rec {
911 pname = "ripgrep";
912 version = "12.1.1";
913
914 src = fetchFromGitHub {
915 owner = "BurntSushi";
916 repo = "ripgrep";
917 rev = version;
918 hash = "sha256-+s5RBC3XSgb8omTbUNLywZnP6jSxZBKSS1BmXOjRF8M=";
919 };
920
921 cargoHash = "sha256-l1vL2ZdtDRxSGvP0X/l3nMw8+6WF67KPutJEzUROjg8=";
922
923 doCheck = false;
924
925 meta = with lib; {
926 description = "A fast line-oriented regex search tool, similar to ag and ack";
927 homepage = "https://github.com/BurntSushi/ripgrep";
928 license = with licenses; [ mit unlicense ];
929 maintainers = with maintainers; [];
930 };
931}
932```
933
934Follow the below steps to try that snippet.
9351. save the above snippet as `default.nix` in that directory
9362. cd into that directory and run `nix-build`
937
938Fenix also has examples with `buildRustPackage`,
939[crane](https://github.com/ipetkov/crane),
940[naersk](https://github.com/nix-community/naersk),
941and cross compilation in its [Examples](https://github.com/nix-community/fenix#examples) section.
942
943## Using `git bisect` on the Rust compiler {#using-git-bisect-on-the-rust-compiler}
944
945Sometimes an upgrade of the Rust compiler (`rustc`) will break a
946downstream package. In these situations, being able to `git bisect`
947the `rustc` version history to find the offending commit is quite
948useful. Nixpkgs makes it easy to do this.
949
950First, roll back your nixpkgs to a commit in which its `rustc` used
951*the most recent one which doesn't have the problem.* You'll need
952to do this because of `rustc`'s extremely aggressive
953version-pinning.
954
955Next, add the following overlay, updating the Rust version to the
956one in your rolled-back nixpkgs, and replacing `/git/scratch/rust`
957with the path into which you have `git clone`d the `rustc` git
958repository:
959
960```nix
961 (final: prev: /*lib.optionalAttrs prev.stdenv.targetPlatform.isAarch64*/ {
962 rust_1_72 =
963 lib.updateManyAttrsByPath [{
964 path = [ "packages" "stable" ];
965 update = old: old.overrideScope(final: prev: {
966 rustc = prev.rustc.overrideAttrs (_: {
967 src = lib.cleanSource /git/scratch/rust;
968 # do *not* put passthru.isReleaseTarball=true here
969 });
970 });
971 }]
972 prev.rust_1_72;
973 })
974```
975
976If the problem you're troubleshooting only manifests when
977cross-compiling you can uncomment the `lib.optionalAttrs` in the
978example above, and replace `isAarch64` with the target that is
979having problems. This will speed up your bisect quite a bit, since
980the host compiler won't need to be rebuilt.
981
982Now, you can start a `git bisect` in the directory where you checked
983out the `rustc` source code. It is recommended to select the
984endpoint commits by searching backwards from `origin/master` for the
985*commits which added the release notes for the versions in
986question.* If you set the endpoints to commits on the release
987branches (i.e. the release tags), git-bisect will often get confused
988by the complex merge-commit structures it will need to traverse.
989
990The command loop you'll want to use for bisecting looks like this:
991
992```bash
993git bisect {good,bad} # depending on result of last build
994git submodule update --init
995CARGO_NET_OFFLINE=false cargo vendor \
996 --sync ./src/tools/cargo/Cargo.toml \
997 --sync ./src/tools/rust-analyzer/Cargo.toml \
998 --sync ./compiler/rustc_codegen_cranelift/Cargo.toml \
999 --sync ./src/bootstrap/Cargo.toml
1000nix-build $NIXPKGS -A package-broken-by-rust-changes
1001```
1002
1003The `git submodule update --init` and `cargo vendor` commands above
1004require network access, so they can't be performed from within the
1005`rustc` derivation, unfortunately.
1006