Home Explore Blog Models CI



nixpkgs

8th chunk of `doc/languages-frameworks/rust.section.md`
b64bc21bb06c089ebb96b9681e69a16a17144bb0585183cc0000000100000fc5
Some projects, especially GNOME applications, are built with the Meson Build System instead of calling Cargo directly. Using `rustPlatform.buildRustPackage` may successfully build the main program, but related files will be missing. Instead, you need to set up Cargo dependencies with `fetchCargoVendor` and `cargoSetupHook` and leave the rest to Meson. `rust` and `cargo` are still needed in `nativeBuildInputs` for Meson to use.

```nix
{
  lib,
  stdenv,
  fetchFromGitLab,
  meson,
  ninja,
  pkg-config,
  rustPlatform,
  rustc,
  cargo,
  wrapGAppsHook4,
  blueprint-compiler,
  libadwaita,
  libsecret,
  tinysparql,
}:

stdenv.mkDerivation (finalAttrs: {
  pname = "health";
  version = "0.95.0";

  src = fetchFromGitLab {
    domain = "gitlab.gnome.org";
    owner = "World";
    repo = "health";
    tag = finalAttrs.version;
    hash = "sha256-PrNPprSS98yN8b8yw2G6hzTSaoE65VbsM3q7FVB4mds=";
  };

  cargoDeps = rustPlatform.fetchCargoVendor {
    inherit (finalAttrs) pname version src;
    hash = "sha256-eR1ZGtTZQNhofFUEjI7IX16sMKPJmAl7aIFfPJukecg=";
  };

  nativeBuildInputs = [
    meson
    ninja
    pkg-config
    rustPlatform.cargoSetupHook
    rustc
    cargo
    wrapGAppsHook4
    blueprint-compiler
  ];

  buildInputs = [
    libadwaita
    libsecret
    tinysparql
  ];

  # ...
})
```

## `buildRustCrate`: Compiling Rust crates using Nix instead of Cargo {#compiling-rust-crates-using-nix-instead-of-cargo}

### Simple operation {#simple-operation}

When run, `cargo build` produces a file called `Cargo.lock`,
containing pinned versions of all dependencies. Nixpkgs contains a
tool called `crate2Nix` (`nix-shell -p crate2nix`), which can be
used to turn a `Cargo.lock` into a Nix expression.  That Nix
expression calls `rustc` directly (hence bypassing Cargo), and can
be used to compile a crate and all its dependencies.

See [`crate2nix`'s documentation](https://github.com/kolloch/crate2nix#known-restrictions)
for instructions on how to use it.

### Handling external dependencies {#handling-external-dependencies}

Some crates require external libraries. For crates from
[crates.io](https://crates.io), such libraries can be specified in
`defaultCrateOverrides` package in nixpkgs itself.

Starting from that file, one can add more overrides, to add features
or build inputs by overriding the hello crate in a separate file.

```nix
with import <nixpkgs> { };
((import ./hello.nix).hello { }).override {
  crateOverrides = defaultCrateOverrides // {
    hello = attrs: { buildInputs = [ openssl ]; };
  };
}
```

Here, `crateOverrides` is expected to be a attribute set, where the
key is the crate name without version number and the value a function.
The function gets all attributes passed to `buildRustCrate` as first
argument and returns a set that contains all attribute that should be
overwritten.

For more complicated cases, such as when parts of the crate's
derivation depend on the crate's version, the `attrs` argument of
the override above can be read, as in the following example, which
patches the derivation:

```nix
with import <nixpkgs> { };
((import ./hello.nix).hello { }).override {
  crateOverrides = defaultCrateOverrides // {
    hello =
      attrs:
      lib.optionalAttrs (lib.versionAtLeast attrs.version "1.0") {
        postPatch = ''
          substituteInPlace lib/zoneinfo.rs \
            --replace-fail "/usr/share/zoneinfo" "${tzdata}/share/zoneinfo"
        '';
      };
  };
}
```

Another situation is when we want to override a nested
dependency. This actually works in the exact same way, since the
`crateOverrides` parameter is forwarded to the crate's
dependencies. For instance, to override the build inputs for crate
`libc` in the example above, where `libc` is a dependency of the main
crate, we could do:

```nix
with import <nixpkgs> { };
((import hello.nix).hello { }).override {
  crateOverrides = defaultCrateOverrides // {
    libc = attrs: { buildInputs = [ ]; };
  };
}
```

### Options and phases configuration {#options-and-phases-configuration}

Title: Nixpkgs Rust Builds: Meson Integration and Direct `rustc` Compilation with `crate2Nix`
Summary
This section first details how to build Rust projects that utilize the Meson Build System, particularly common in GNOME applications. It advises against `rustPlatform.buildRustPackage` for such cases, instead recommending `fetchCargoVendor` and `cargoSetupHook` for managing Cargo dependencies while allowing Meson to handle the primary build process, ensuring `rustc` and `cargo` are included in `nativeBuildInputs`. An example for the 'health' application is provided. The document then introduces `buildRustCrate`, an alternative method for compiling Rust crates directly using Nix, bypassing Cargo. This involves `crate2Nix` to convert a `Cargo.lock` file into a Nix expression that calls `rustc` directly. It further explains how to handle external dependencies by using `crateOverrides` to add build inputs, features, or other attributes to specific crates, supporting conditional overrides based on crate versions and even overriding nested dependencies.