# fenix Fenix provides the `minimal`, `default`, and `complete` [profile](https://rust-lang.github.io/rustup/concepts/profiles.html) of rust toolchains, [`latest`](#latest) profile of nightly toolchains, nightly version of [rust analyzer](https://rust-analyzer.github.io) and [its vscode extension](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer). It aims to be a replacement for [rustup](https://rustup.rs) and the rust overlay provided by [nixpkgs-mozilla](https://github.com/mozilla/nixpkgs-mozilla). Binary cache is available for `x86_64-darwin`, `aarch64-darwin` and `x86_64-linux` on [cachix](https://app.cachix.org/cache/fenix) ```sh 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](https://github.com/nix-community/fenix/issues/79)) ```nix { nixpkgs.overlays = [ (_: super: let pkgs = fenix.inputs.nixpkgs.legacyPackages.${super.system}; in fenix.overlays.default pkgs pkgs) ]; } ``` - [Usage](#usage) - [Monthly branch](#monthly-branch) - [Supported platforms and targets](#supported-platforms-and-targets) - [Examples](#examples) - [Contributing](#contributing) ## Usage
As a flake (recommended) ```nix { 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 ```nix let fenix = import (fetchTarball "https://github.com/nix-community/fenix/archive/main.tar.gz") { }; in fenix.minimal.toolchain ```
As an overlay ```nix # 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.;` (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: ```nix { # components cargo = ; rustc = ; # rustc with rust-std rustc-unwrapped = ; # rustc without rust-std, same as rustc.unwrapped rustfmt = ; # alias to rustfmt-preview rust-src = ; # RUST_SRC_PATH = "${fenix.complete.rust-src}/lib/rustlib/src/rust/library" # ... # derivation with all the components toolchain = ; # not available in nightly toolchains # derivation with all the components from a profile minimalToolchain = ; defaultToolchain = ; completeToolchain = ; # withComponents : [string] -> derivation # creates a derivation with the given list of components from the toolchain withComponents = ; } ```
combine : [derivation] -> derivation Combines a list of components into a derivation. If the components are from the same toolchain, use `withComponents` instead. ```nix combine [ minimal.rustc minimal.cargo targets.wasm32-unknown-unknown.latest.rust-std ] ```
fromManifest : attrs -> toolchain Creates a [toolchain](#toolchain) from a rustup manifest ```nix fromManifest (lib.importTOML ./channel-rust-nightly.toml) ```
fromManifestFile : path -> toolchain Creates a [toolchain](#toolchain) from a rustup manifest file ```nix fromManifestFile ./channel-rust-nightly.toml ```
toolchainOf : attrs -> toolchain Creates [toolchain](#toolchain) from given arguments: argument | default | description -|-|- 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 date | `null` | date of the toolchain, latest if unset sha256 | `null` | sha256 of the manifest, required in pure evaluation mode, set to `lib.fakeSha256` to get the actual sha256 from the error message ```nix toolchainOf { channel = "beta"; date = "2021-08-29"; sha256 = "0dkmjil9avba6l0l9apmgwa8d0h4f8jzgxkq3gvn8d2xc68ks5a5"; } ``` ```nix toolchainOf { channel = "1.90.0"; sha256 = "sha256-SJwZ8g0zF2WrKDVmHrVG3pD2RGoQeo24MEXnNx5FyuI="; } ```
fromToolchainFile : attrs -> derivation Creates a derivation from a [rust toolchain file](https://rust-lang.github.io/rustup/overrides.html#the-toolchain-file), accepts the following arguments: argument | description -|- file | path to the rust toolchain file, usually either `./rust-toolchain` or `./rust-toolchain.toml`, conflicts with `dir` dir | path to the directory that has `rust-toolchain` or `rust-toolchain.toml`, conflicts with `file` sha256 | sha256 of the manifest, required in pure evaluation mode, set to `lib.fakeSha256` to get the actual sha256 from the error message ```nix fromToolchainFile { file = ./rust-toolchain.toml; sha256 = lib.fakeSha256; } ``` ```nix fromToolchainFile { dir = ./.; } ```
fromToolchainName : attrs -> toolchain Creates a [toolchain](#toolchain) from a toolchain name, accepts the following arguments: argument | description -|- name | rust channel, version number, one of `"stable"`, `"beta"`, `"nightly"`, and date. sha256 | sha256 of the manifest, required in pure evaluation mode, set to `lib.fakeSha256` to get the actual sha256 from the error message ```nix fromToolchainName { name = "1.90.0"; sha256 = "sha256-SJwZ8g0zF2WrKDVmHrVG3pD2RGoQeo24MEXnNx5FyuI="; } ``` ```nix fromToolchainName { name = "nightly-2023-08-07"; sha256 = "Ho2/rJSi6KiHbxgDpdvYE0dwrEUD3psnyYyLmFNYKII="; } ``` ```nix fromToolchainName { name = (lib.importTOML ./rust-toolchain.toml).toolchain.channel; } ```
stable : toolchain The stable [toolchain](#toolchain)
beta : toolchain The beta [toolchain](#toolchain)
minimal : toolchain The minimal profile of the nightly [toolchain](#toolchain)
default : toolchain The default profile of the nightly [toolchain](#toolchain), sometimes lags behind the `minimal` profile
complete : toolchain The complete profile of the nightly [toolchain](#toolchain), usually lags behind the `minimal` and `default` profile
latest : toolchain A custom [toolchain](#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 [Toolchain](#toolchain)s for [supported targets](#supported-platforms-and-targets), everything mentioned above except for `combine` is supported ```nix targets.wasm32-unknown-unknown.latest.rust-std ```
rust-analyzer : derivation Nightly version of `rust-analyzer`, also available with overlay as `rust-analyzer-nightly` ```nix # 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` ```nix # 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. ```nix { 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 | platform | target | -|- aarch64-darwin | aarch64-apple-darwin aarch64-linux | aarch64-unknown-linux-gnu i686-linux | i686-unknown-linux-gnu x86_64-darwin | x86_64-apple-darwin x86_64-linux | x86_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 ```nix { 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 ```nix { 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 ```nix { 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 ```nix { 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`: ```nix nativeBuildInputs = with pkgs; [ llvmPackages.bintools libclang.lib ] ++ lib.optional stdenv.hostPlatform.isLinux pkgs.autoPatchelfHook; buildInputs = lib.optional stdenv.hostPlatform.isDarwin pkgs.libiconv ++ lib.optionals stdenv.hostPlatform.isLinux (with pkgs; [ gcc.cc gcc.cc.lib ]); ``` Then tell cargo to use `lld`. See the [cargo book](https://doc.rust-lang.org/cargo/guide/build-performance.html#use-an-alternative-linker) 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