nix-community/fenix

Rust toolchains and rust-analyzer nightly for Nix [maintainers=@figsoda, @eureka-cpu]

1,116

stars

2,764

commits

Nix

primary language

Sep 11, 2026

updated

flake
flakes
nightly
nix
overlay
rust

README

fenix

Fenix provides the minimal, default, and complete profile of rust toolchains, latest profile of nightly toolchains, nightly version of rust analyzer and its vscode extension. It aims to be a replacement for rustup and the rust overlay provided by nixpkgs-mozilla.

Binary cache is available for x86_64-darwin, aarch64-darwin and x86_64-linux on cachix

cachix use fenix

Note: The nixpkgs from your system will be used when fenix is being used as an overlay, which may not be cached if you are using a stable/older version of nixpkgs. To fix this, use the packages directly or use the following workaround (see #79)

{
  nixpkgs.overlays = [
    (_: super: let pkgs = fenix.inputs.nixpkgs.legacyPackages.${super.system}; in fenix.overlays.default pkgs pkgs)
  ];
}

Usage

As a flake (recommended)
{
  inputs = {
    fenix = {
      url = "github:nix-community/fenix";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    nixpkgs.url = "nixpkgs/nixos-unstable";
  };

  outputs = { self, fenix, nixpkgs }: {
    packages.x86_64-linux.default = fenix.packages.x86_64-linux.minimal.toolchain;
    nixosConfigurations.nixos = nixpkgs.lib.nixosSystem {
      system = "x86_64-linux";
      modules = [
        ({ pkgs, ... }: {
          nixpkgs.overlays = [ fenix.overlays.default ];
          environment.systemPackages = [
            (pkgs.fenix.complete.withComponents [
              "cargo"
              "clippy"
              "rust-src"
              "rustc"
              "rustfmt"
            ])
            pkgs.rust-analyzer-nightly
          ];
        })
      ];
    };
  };
}
As a set of packages
let
  fenix = import (fetchTarball "https://github.com/nix-community/fenix/archive/main.tar.gz") { };
in
fenix.minimal.toolchain
As an overlay
# configuration.nix
{ pkgs, ... }: {
  nixpkgs.overlays = [
    (import "${fetchTarball "https://github.com/nix-community/fenix/archive/main.tar.gz"}/overlay.nix")
  ];
  environment.systemPackages = with pkgs; [
    (fenix.complete.withComponents [
      "cargo"
      "clippy"
      "rust-src"
      "rustc"
      "rustfmt"
    ])
    rust-analyzer-nightly
  ];
}

Following is a list of outputs, examples are prefixed with:

  • with fenix.packages.<system>; (flakes), or
  • with import (fetchTarball "https://github.com/nix-community/fenix/archive/main.tar.gz") { };

Some outputs are toolchains, a rust toolchain in fenix is structured like this:

{
  # components
  cargo = <derivation>;
  rustc = <derivation>; # rustc with rust-std
  rustc-unwrapped = <derivation>; # rustc without rust-std, same as rustc.unwrapped
  rustfmt = <derivation>; # alias to rustfmt-preview
  rust-src = <derivation>; # RUST_SRC_PATH = "${fenix.complete.rust-src}/lib/rustlib/src/rust/library"
  # ...

  # derivation with all the components
  toolchain = <derivation>;

  # not available in nightly toolchains
  # derivation with all the components from a profile
  minimalToolchain = <derivation>;
  defaultToolchain = <derivation>;
  completeToolchain = <derivation>;

  # withComponents : [string] -> derivation
  # creates a derivation with the given list of components from the toolchain
  withComponents = <function>;
}
combine : [derivation] -> derivation

Combines a list of components into a derivation. If the components are from the same toolchain, use withComponents instead.

combine [
  minimal.rustc
  minimal.cargo
  targets.wasm32-unknown-unknown.latest.rust-std
]
fromManifest : attrs -> toolchain

Creates a toolchain from a rustup manifest

fromManifest (lib.importTOML ./channel-rust-nightly.toml)
fromManifestFile : path -> toolchain

Creates a toolchain from a rustup manifest file

fromManifestFile ./channel-rust-nightly.toml
toolchainOf : attrs -> toolchain

Creates toolchain from given arguments:

argumentdefaultdescription
root"https://static.rust-lang.org/dist"root url from downloading manifest, usually left as default
channel"nightly"rust channel, one of "stable", "beta", "nightly", and version number
datenulldate of the toolchain, latest if unset
sha256nullsha256 of the manifest, required in pure evaluation mode, set to lib.fakeSha256 to get the actual sha256 from the error message
toolchainOf {
  channel = "beta";
  date = "2021-08-29";
  sha256 = "0dkmjil9avba6l0l9apmgwa8d0h4f8jzgxkq3gvn8d2xc68ks5a5";
}
toolchainOf {
  channel = "1.90.0";
  sha256 = "sha256-SJwZ8g0zF2WrKDVmHrVG3pD2RGoQeo24MEXnNx5FyuI=";
}
fromToolchainFile : attrs -> derivation

Creates a derivation from a rust toolchain file, accepts the following arguments:

argumentdescription
filepath to the rust toolchain file, usually either ./rust-toolchain or ./rust-toolchain.toml, conflicts with dir
dirpath to the directory that has rust-toolchain or rust-toolchain.toml, conflicts with file
sha256sha256 of the manifest, required in pure evaluation mode, set to lib.fakeSha256 to get the actual sha256 from the error message
fromToolchainFile {
  file = ./rust-toolchain.toml;
  sha256 = lib.fakeSha256;
}
fromToolchainFile { dir = ./.; }
fromToolchainName : attrs -> toolchain

Creates a toolchain from a toolchain name, accepts the following arguments:

argumentdescription
namerust channel, version number, one of "stable", "beta", "nightly", and date.
sha256sha256 of the manifest, required in pure evaluation mode, set to lib.fakeSha256 to get the actual sha256 from the error message
fromToolchainName { name = "1.90.0"; sha256 = "sha256-SJwZ8g0zF2WrKDVmHrVG3pD2RGoQeo24MEXnNx5FyuI="; }
fromToolchainName { name = "nightly-2023-08-07"; sha256 = "Ho2/rJSi6KiHbxgDpdvYE0dwrEUD3psnyYyLmFNYKII="; }
fromToolchainName { name = (lib.importTOML ./rust-toolchain.toml).toolchain.channel; }
stable : toolchain

The stable toolchain

beta : toolchain

The beta toolchain

minimal : toolchain

The minimal profile of the nightly toolchain

default : toolchain

The default profile of the nightly toolchain, sometimes lags behind the minimal profile

complete : toolchain

The complete profile of the nightly toolchain, usually lags behind the minimal and default profile

latest : toolchain

A custom toolchain that contains all the components from the complete profile but not from necessarily the same date. Unlike the complete profile, you get the latest version of the components, but risks a larger chance of incompatibility.

targets.${target}.* : toolchain

Toolchains for supported targets, everything mentioned above except for combine is supported

targets.wasm32-unknown-unknown.latest.rust-std
rust-analyzer : derivation

Nightly version of rust-analyzer, also available with overlay as rust-analyzer-nightly

# configuration.nix with overlay
{ pkgs, ... }: {
  environment.systemPackages = with pkgs; [ rust-analyzer-nightly ];
}
rust-analyzer-vscode-extension : derivation

Nightly version of vscode-extensions.rust-lang.rust-analyzer, also available with overlay as vscode-extensions.rust-lang.rust-analyzer-nightly

# with overlay
with pkgs; vscode-with-extensions.override {
  vscodeExtensions = [
    vscode-extensions.rust-lang.rust-analyzer-nightly
  ];
}

Monthly branch

Fenix has a monthly branch that is updated on the 1st of every month, for cases where you want to use rust nightly but don't need it to be updated very often.

{
  inputs = {
    fenix.url = "github:nix-community/fenix/monthly";
  };

  outputs = { self, fenix }: {
    packages.x86_64-linux.default = fenix.packages.x86_64-linux.default.toolchain;
  };
}

Supported platforms and targets

platformtarget
aarch64-darwinaarch64-apple-darwin
aarch64-linuxaarch64-unknown-linux-gnu
i686-linuxi686-unknown-linux-gnu
x86_64-darwinx86_64-apple-darwin
x86_64-linuxx86_64-unknown-linux-gnu
only rust-std (for cross compiling)
  • aarch64-apple-darwin
  • aarch64-apple-ios
  • aarch64-linux-android
  • aarch64-pc-windows-msvc
  • aarch64-unknown-fuchsia
  • aarch64-unknown-linux-musl
  • arm-linux-androideabi
  • arm-unknown-linux-gnueabi
  • arm-unknown-linux-gnueabihf
  • arm-unknown-linux-musleabi
  • arm-unknown-linux-musleabihf
  • armv5te-unknown-linux-gnueabi
  • armv7-linux-androideabi
  • armv7-unknown-linux-gnueabihf
  • armv7-unknown-linux-musleabihf
  • asmjs-unknown-emscripten
  • i586-pc-windows-msvc
  • i586-unknown-linux-gnu
  • i586-unknown-linux-musl
  • i686-linux-android
  • i686-pc-windows-gnu
  • i686-pc-windows-msvc
  • i686-unknown-freebsd
  • i686-unknown-linux-musl
  • mips-unknown-linux-gnu
  • mips-unknown-linux-musl
  • mips64-unknown-linux-gnuabi64
  • mips64el-unknown-linux-gnuabi64
  • mipsel-unknown-linux-gnu
  • mipsel-unknown-linux-musl
  • powerpc-unknown-linux-gnu
  • powerpc64-unknown-linux-gnu
  • powerpc64le-unknown-linux-gnu
  • s390x-unknown-linux-gnu
  • sparc64-unknown-linux-gnu
  • sparcv9-sun-solaris
  • wasm32-unknown-emscripten
  • wasm32-unknown-unknown
  • x86_64-apple-ios
  • x86_64-linux-android
  • x86_64-pc-windows-gnu
  • x86_64-pc-windows-msvc
  • x86_64-rumprun-netbsd
  • x86_64-sun-solaris
  • x86_64-unknown-freebsd
  • x86_64-unknown-fuchsia
  • x86_64-unknown-illumos
  • x86_64-unknown-linux-gnux32
  • x86_64-unknown-linux-musl
  • x86_64-unknown-netbsd
  • x86_64-unknown-redox

Examples

building with makeRustPlatform
{
  inputs = {
    fenix = {
      url = "github:nix-community/fenix";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    flake-utils.url = "github:numtide/flake-utils";
    nixpkgs.url = "nixpkgs/nixos-unstable";
  };

  outputs = { self, fenix, flake-utils, nixpkgs }:
    flake-utils.lib.eachDefaultSystem (system: {
      packages.default =
        let
          toolchain = fenix.packages.${system}.minimal.toolchain;
          pkgs = nixpkgs.legacyPackages.${system};
        in

        (pkgs.makeRustPlatform {
          cargo = toolchain;
          rustc = toolchain;
        }).buildRustPackage {
          pname = "example";
          version = "0.1.0";

          src = ./.;

          cargoLock.lockFile = ./Cargo.lock;
        };
    });
}
building with crane
{
  inputs = {
    crane = {
      url = "github:ipetkov/crane";
      inputs = {
        flake-utils.follows = "flake-utils";
        nixpkgs.follows = "nixpkgs";
      };
    };
    fenix = {
      url = "github:nix-community/fenix";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    flake-utils.url = "github:numtide/flake-utils";
    nixpkgs.url = "nixpkgs/nixos-unstable";
  };

  outputs = { self, crane, fenix, flake-utils, nixpkgs }:
    flake-utils.lib.eachDefaultSystem (system: {
      packages.default =
        let
          craneLib = (crane.mkLib nixpkgs.legacyPackages.${system}).overrideToolchain fenix.packages.${system}.stable.toolchain;
        in

        craneLib.buildPackage {
          src = ./.;
        };
    });
}
cross compiling with naersk
{
  inputs = {
    fenix = {
      url = "github:nix-community/fenix";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    flake-utils.url = "github:numtide/flake-utils";
    naersk = {
      url = "github:nix-community/naersk";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    nixpkgs.url = "nixpkgs/nixos-unstable";
  };

  outputs = { self, fenix, flake-utils, naersk, nixpkgs }:
    flake-utils.lib.eachDefaultSystem (system: {
      packages.default =
        let
          pkgs = nixpkgs.legacyPackages.${system};
          target = "aarch64-unknown-linux-gnu";
          toolchain = with fenix.packages.${system}; combine [
            minimal.cargo
            minimal.rustc
            targets.${target}.latest.rust-std
          ];
        in

        (naersk.lib.${system}.override {
          cargo = toolchain;
          rustc = toolchain;
        }).buildPackage {
          src = ./.;
          CARGO_BUILD_TARGET = target;
          CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER =
            let
              inherit (pkgs.pkgsCross.aarch64-multiplatform.stdenv) cc;
            in
            "${cc}/bin/${cc.targetPrefix}cc";
        };
    });
}
pinning to a specific version of rust without using IFD
{
  inputs = {
    fenix = {
      url = "github:nix-community/fenix";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    nixpkgs.url = "nixpkgs/nixos-unstable";
    rust-manifest = {
      url = "https://static.rust-lang.org/dist/channel-rust-stable.toml";
      flake = false;
    };
  };

  outputs = { self, fenix, nixpkgs, rust-manifest }: {
    packages.x86_64-linux.default =
      (fenix.packages.x86_64-linux.fromManifestFile rust-manifest).minimalToolchain;
  };
}

Overriding the linker

Some cross-compilation targets fail with a linker error like:

= note: rust-lld: error: /nix/store/.../libgcc_s.so.1 is incompatible with elf32-i386

Fenix only provides the Rust toolchain, so it doesn't control which system linker cargo ends up invoking during cross compilation. If the default linker doesn't support your target, you can switch to lld from LLVM instead.

First, make lld and the libraries it needs available to your build, e.g. in your cargo derivation's nativeBuildInputs/buildInputs:

nativeBuildInputs = with pkgs; [
  llvmPackages.bintools
  libclang.lib
] ++ lib.optional stdenv.isLinux pkgs.autoPatchelfHook;

buildInputs = lib.optional stdenv.isDarwin pkgs.libiconv
  ++ lib.optionals stdenv.isLinux (with pkgs; [
    gcc.cc
    gcc.cc.lib
  ]);

Then tell cargo to use lld. See the cargo book for the full set of linker options; the relevant flag here is -Clink-arg=-fuse-ld=lld.

Prefer setting this via an environment variable or a build flag on your cargo derivation, e.g. RUSTFLAGS = "-Clink-arg=-fuse-ld=lld";, rather than committing a .cargo/config.toml to your project. A config file becomes part of the derivation's source, which locks the linker choice in for every build of that source, including ones that don't need it. An env var or flag only affects the specific build that requires it.

Contributing

All pull requests should target staging branch instead of the default main branch

Contributors

(top 30 of 33)

actions-user

2,385 commits

figsoda

288 commits

dependabot[bot]

44 commits

eureka-cpu

5 commits

nix-community/fenix

Rust toolchains and rust-analyzer nightly for Nix [maintainers=@figsoda, @eureka-cpu]

1,116

stars

2,764

commits

Nix

primary language

Sep 11, 2026

updated

flake
flakes
nightly
nix
overlay
rust

README

fenix

Fenix provides the minimal, default, and complete profile of rust toolchains, latest profile of nightly toolchains, nightly version of rust analyzer and its vscode extension. It aims to be a replacement for rustup and the rust overlay provided by nixpkgs-mozilla.

Binary cache is available for x86_64-darwin, aarch64-darwin and x86_64-linux on cachix

cachix use fenix

Note: The nixpkgs from your system will be used when fenix is being used as an overlay, which may not be cached if you are using a stable/older version of nixpkgs. To fix this, use the packages directly or use the following workaround (see #79)

{
  nixpkgs.overlays = [
    (_: super: let pkgs = fenix.inputs.nixpkgs.legacyPackages.${super.system}; in fenix.overlays.default pkgs pkgs)
  ];
}

Usage

As a flake (recommended)
{
  inputs = {
    fenix = {
      url = "github:nix-community/fenix";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    nixpkgs.url = "nixpkgs/nixos-unstable";
  };

  outputs = { self, fenix, nixpkgs }: {
    packages.x86_64-linux.default = fenix.packages.x86_64-linux.minimal.toolchain;
    nixosConfigurations.nixos = nixpkgs.lib.nixosSystem {
      system = "x86_64-linux";
      modules = [
        ({ pkgs, ... }: {
          nixpkgs.overlays = [ fenix.overlays.default ];
          environment.systemPackages = [
            (pkgs.fenix.complete.withComponents [
              "cargo"
              "clippy"
              "rust-src"
              "rustc"
              "rustfmt"
            ])
            pkgs.rust-analyzer-nightly
          ];
        })
      ];
    };
  };
}
As a set of packages
let
  fenix = import (fetchTarball "https://github.com/nix-community/fenix/archive/main.tar.gz") { };
in
fenix.minimal.toolchain
As an overlay
# configuration.nix
{ pkgs, ... }: {
  nixpkgs.overlays = [
    (import "${fetchTarball "https://github.com/nix-community/fenix/archive/main.tar.gz"}/overlay.nix")
  ];
  environment.systemPackages = with pkgs; [
    (fenix.complete.withComponents [
      "cargo"
      "clippy"
      "rust-src"
      "rustc"
      "rustfmt"
    ])
    rust-analyzer-nightly
  ];
}

Following is a list of outputs, examples are prefixed with:

  • with fenix.packages.<system>; (flakes), or
  • with import (fetchTarball "https://github.com/nix-community/fenix/archive/main.tar.gz") { };

Some outputs are toolchains, a rust toolchain in fenix is structured like this:

{
  # components
  cargo = <derivation>;
  rustc = <derivation>; # rustc with rust-std
  rustc-unwrapped = <derivation>; # rustc without rust-std, same as rustc.unwrapped
  rustfmt = <derivation>; # alias to rustfmt-preview
  rust-src = <derivation>; # RUST_SRC_PATH = "${fenix.complete.rust-src}/lib/rustlib/src/rust/library"
  # ...

  # derivation with all the components
  toolchain = <derivation>;

  # not available in nightly toolchains
  # derivation with all the components from a profile
  minimalToolchain = <derivation>;
  defaultToolchain = <derivation>;
  completeToolchain = <derivation>;

  # withComponents : [string] -> derivation
  # creates a derivation with the given list of components from the toolchain
  withComponents = <function>;
}
combine : [derivation] -> derivation

Combines a list of components into a derivation. If the components are from the same toolchain, use withComponents instead.

combine [
  minimal.rustc
  minimal.cargo
  targets.wasm32-unknown-unknown.latest.rust-std
]
fromManifest : attrs -> toolchain

Creates a toolchain from a rustup manifest

fromManifest (lib.importTOML ./channel-rust-nightly.toml)
fromManifestFile : path -> toolchain

Creates a toolchain from a rustup manifest file

fromManifestFile ./channel-rust-nightly.toml
toolchainOf : attrs -> toolchain

Creates toolchain from given arguments:

argumentdefaultdescription
root"https://static.rust-lang.org/dist"root url from downloading manifest, usually left as default
channel"nightly"rust channel, one of "stable", "beta", "nightly", and version number
datenulldate of the toolchain, latest if unset
sha256nullsha256 of the manifest, required in pure evaluation mode, set to lib.fakeSha256 to get the actual sha256 from the error message
toolchainOf {
  channel = "beta";
  date = "2021-08-29";
  sha256 = "0dkmjil9avba6l0l9apmgwa8d0h4f8jzgxkq3gvn8d2xc68ks5a5";
}
toolchainOf {
  channel = "1.90.0";
  sha256 = "sha256-SJwZ8g0zF2WrKDVmHrVG3pD2RGoQeo24MEXnNx5FyuI=";
}
fromToolchainFile : attrs -> derivation

Creates a derivation from a rust toolchain file, accepts the following arguments:

argumentdescription
filepath to the rust toolchain file, usually either ./rust-toolchain or ./rust-toolchain.toml, conflicts with dir
dirpath to the directory that has rust-toolchain or rust-toolchain.toml, conflicts with file
sha256sha256 of the manifest, required in pure evaluation mode, set to lib.fakeSha256 to get the actual sha256 from the error message
fromToolchainFile {
  file = ./rust-toolchain.toml;
  sha256 = lib.fakeSha256;
}
fromToolchainFile { dir = ./.; }
fromToolchainName : attrs -> toolchain

Creates a toolchain from a toolchain name, accepts the following arguments:

argumentdescription
namerust channel, version number, one of "stable", "beta", "nightly", and date.
sha256sha256 of the manifest, required in pure evaluation mode, set to lib.fakeSha256 to get the actual sha256 from the error message
fromToolchainName { name = "1.90.0"; sha256 = "sha256-SJwZ8g0zF2WrKDVmHrVG3pD2RGoQeo24MEXnNx5FyuI="; }
fromToolchainName { name = "nightly-2023-08-07"; sha256 = "Ho2/rJSi6KiHbxgDpdvYE0dwrEUD3psnyYyLmFNYKII="; }
fromToolchainName { name = (lib.importTOML ./rust-toolchain.toml).toolchain.channel; }
stable : toolchain

The stable toolchain

beta : toolchain

The beta toolchain

minimal : toolchain

The minimal profile of the nightly toolchain

default : toolchain

The default profile of the nightly toolchain, sometimes lags behind the minimal profile

complete : toolchain

The complete profile of the nightly toolchain, usually lags behind the minimal and default profile

latest : toolchain

A custom toolchain that contains all the components from the complete profile but not from necessarily the same date. Unlike the complete profile, you get the latest version of the components, but risks a larger chance of incompatibility.

targets.${target}.* : toolchain

Toolchains for supported targets, everything mentioned above except for combine is supported

targets.wasm32-unknown-unknown.latest.rust-std
rust-analyzer : derivation

Nightly version of rust-analyzer, also available with overlay as rust-analyzer-nightly

# configuration.nix with overlay
{ pkgs, ... }: {
  environment.systemPackages = with pkgs; [ rust-analyzer-nightly ];
}
rust-analyzer-vscode-extension : derivation

Nightly version of vscode-extensions.rust-lang.rust-analyzer, also available with overlay as vscode-extensions.rust-lang.rust-analyzer-nightly

# with overlay
with pkgs; vscode-with-extensions.override {
  vscodeExtensions = [
    vscode-extensions.rust-lang.rust-analyzer-nightly
  ];
}

Monthly branch

Fenix has a monthly branch that is updated on the 1st of every month, for cases where you want to use rust nightly but don't need it to be updated very often.

{
  inputs = {
    fenix.url = "github:nix-community/fenix/monthly";
  };

  outputs = { self, fenix }: {
    packages.x86_64-linux.default = fenix.packages.x86_64-linux.default.toolchain;
  };
}

Supported platforms and targets

platformtarget
aarch64-darwinaarch64-apple-darwin
aarch64-linuxaarch64-unknown-linux-gnu
i686-linuxi686-unknown-linux-gnu
x86_64-darwinx86_64-apple-darwin
x86_64-linuxx86_64-unknown-linux-gnu
only rust-std (for cross compiling)
  • aarch64-apple-darwin
  • aarch64-apple-ios
  • aarch64-linux-android
  • aarch64-pc-windows-msvc
  • aarch64-unknown-fuchsia
  • aarch64-unknown-linux-musl
  • arm-linux-androideabi
  • arm-unknown-linux-gnueabi
  • arm-unknown-linux-gnueabihf
  • arm-unknown-linux-musleabi
  • arm-unknown-linux-musleabihf
  • armv5te-unknown-linux-gnueabi
  • armv7-linux-androideabi
  • armv7-unknown-linux-gnueabihf
  • armv7-unknown-linux-musleabihf
  • asmjs-unknown-emscripten
  • i586-pc-windows-msvc
  • i586-unknown-linux-gnu
  • i586-unknown-linux-musl
  • i686-linux-android
  • i686-pc-windows-gnu
  • i686-pc-windows-msvc
  • i686-unknown-freebsd
  • i686-unknown-linux-musl
  • mips-unknown-linux-gnu
  • mips-unknown-linux-musl
  • mips64-unknown-linux-gnuabi64
  • mips64el-unknown-linux-gnuabi64
  • mipsel-unknown-linux-gnu
  • mipsel-unknown-linux-musl
  • powerpc-unknown-linux-gnu
  • powerpc64-unknown-linux-gnu
  • powerpc64le-unknown-linux-gnu
  • s390x-unknown-linux-gnu
  • sparc64-unknown-linux-gnu
  • sparcv9-sun-solaris
  • wasm32-unknown-emscripten
  • wasm32-unknown-unknown
  • x86_64-apple-ios
  • x86_64-linux-android
  • x86_64-pc-windows-gnu
  • x86_64-pc-windows-msvc
  • x86_64-rumprun-netbsd
  • x86_64-sun-solaris
  • x86_64-unknown-freebsd
  • x86_64-unknown-fuchsia
  • x86_64-unknown-illumos
  • x86_64-unknown-linux-gnux32
  • x86_64-unknown-linux-musl
  • x86_64-unknown-netbsd
  • x86_64-unknown-redox

Examples

building with makeRustPlatform
{
  inputs = {
    fenix = {
      url = "github:nix-community/fenix";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    flake-utils.url = "github:numtide/flake-utils";
    nixpkgs.url = "nixpkgs/nixos-unstable";
  };

  outputs = { self, fenix, flake-utils, nixpkgs }:
    flake-utils.lib.eachDefaultSystem (system: {
      packages.default =
        let
          toolchain = fenix.packages.${system}.minimal.toolchain;
          pkgs = nixpkgs.legacyPackages.${system};
        in

        (pkgs.makeRustPlatform {
          cargo = toolchain;
          rustc = toolchain;
        }).buildRustPackage {
          pname = "example";
          version = "0.1.0";

          src = ./.;

          cargoLock.lockFile = ./Cargo.lock;
        };
    });
}
building with crane
{
  inputs = {
    crane = {
      url = "github:ipetkov/crane";
      inputs = {
        flake-utils.follows = "flake-utils";
        nixpkgs.follows = "nixpkgs";
      };
    };
    fenix = {
      url = "github:nix-community/fenix";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    flake-utils.url = "github:numtide/flake-utils";
    nixpkgs.url = "nixpkgs/nixos-unstable";
  };

  outputs = { self, crane, fenix, flake-utils, nixpkgs }:
    flake-utils.lib.eachDefaultSystem (system: {
      packages.default =
        let
          craneLib = (crane.mkLib nixpkgs.legacyPackages.${system}).overrideToolchain fenix.packages.${system}.stable.toolchain;
        in

        craneLib.buildPackage {
          src = ./.;
        };
    });
}
cross compiling with naersk
{
  inputs = {
    fenix = {
      url = "github:nix-community/fenix";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    flake-utils.url = "github:numtide/flake-utils";
    naersk = {
      url = "github:nix-community/naersk";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    nixpkgs.url = "nixpkgs/nixos-unstable";
  };

  outputs = { self, fenix, flake-utils, naersk, nixpkgs }:
    flake-utils.lib.eachDefaultSystem (system: {
      packages.default =
        let
          pkgs = nixpkgs.legacyPackages.${system};
          target = "aarch64-unknown-linux-gnu";
          toolchain = with fenix.packages.${system}; combine [
            minimal.cargo
            minimal.rustc
            targets.${target}.latest.rust-std
          ];
        in

        (naersk.lib.${system}.override {
          cargo = toolchain;
          rustc = toolchain;
        }).buildPackage {
          src = ./.;
          CARGO_BUILD_TARGET = target;
          CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER =
            let
              inherit (pkgs.pkgsCross.aarch64-multiplatform.stdenv) cc;
            in
            "${cc}/bin/${cc.targetPrefix}cc";
        };
    });
}
pinning to a specific version of rust without using IFD
{
  inputs = {
    fenix = {
      url = "github:nix-community/fenix";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    nixpkgs.url = "nixpkgs/nixos-unstable";
    rust-manifest = {
      url = "https://static.rust-lang.org/dist/channel-rust-stable.toml";
      flake = false;
    };
  };

  outputs = { self, fenix, nixpkgs, rust-manifest }: {
    packages.x86_64-linux.default =
      (fenix.packages.x86_64-linux.fromManifestFile rust-manifest).minimalToolchain;
  };
}

Overriding the linker

Some cross-compilation targets fail with a linker error like:

= note: rust-lld: error: /nix/store/.../libgcc_s.so.1 is incompatible with elf32-i386

Fenix only provides the Rust toolchain, so it doesn't control which system linker cargo ends up invoking during cross compilation. If the default linker doesn't support your target, you can switch to lld from LLVM instead.

First, make lld and the libraries it needs available to your build, e.g. in your cargo derivation's nativeBuildInputs/buildInputs:

nativeBuildInputs = with pkgs; [
  llvmPackages.bintools
  libclang.lib
] ++ lib.optional stdenv.isLinux pkgs.autoPatchelfHook;

buildInputs = lib.optional stdenv.isDarwin pkgs.libiconv
  ++ lib.optionals stdenv.isLinux (with pkgs; [
    gcc.cc
    gcc.cc.lib
  ]);

Then tell cargo to use lld. See the cargo book for the full set of linker options; the relevant flag here is -Clink-arg=-fuse-ld=lld.

Prefer setting this via an environment variable or a build flag on your cargo derivation, e.g. RUSTFLAGS = "-Clink-arg=-fuse-ld=lld";, rather than committing a .cargo/config.toml to your project. A config file becomes part of the derivation's source, which locks the linker choice in for every build of that source, including ones that don't need it. An env var or flag only affects the specific build that requires it.

Contributing

All pull requests should target staging branch instead of the default main branch

Contributors

(top 30 of 33)

actions-user

2,385 commits

figsoda

288 commits

dependabot[bot]

44 commits

eureka-cpu

5 commits

Languages

Nix

78.0%

Python

20.2%

Shell

1.8%