Home Explore Blog CI



nixpkgs

8th chunk of `doc/languages-frameworks/rust.section.md`
592400c381fe633fc890751bbebe81a8a5a57bc11ad8314e0000000100000fc5
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: Building Rust Crates with Nix Directly and Configuration Options
Summary
This section describes how to compile Rust crates using Nix directly instead of Cargo. It uses `crate2Nix` to convert a `Cargo.lock` file into a Nix expression that calls `rustc` directly. It also covers handling external dependencies by specifying them in `defaultCrateOverrides` and overriding crate attributes. In addition it shows how to patch derivations based on crate versions. Finally, nested dependencies can be configured by using the `crateOverrides` parameter.