Create nix develop-shell for rust with mold

Here is the flake.nix:

{
  description = "NixOS configuration";

  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/master";
    rust-overlay.url = "github:oxalica/rust-overlay";
  };

  outputs = { nixpkgs, rust-overlay, ... }:
    let
      system = "x86_64-linux";
      pkgs = import nixpkgs {
        inherit system;

        overlays = [ rust-overlay.overlays.default ];
      };
    in
    {
      devShells.${system}.default = pkgs.mkShell {
        packages = with pkgs; [
          rust-bin.stable.latest.default
        ];

        RUSTC_LINKER = "${pkgs.llvmPackages.clangUseLLVM}/bin/clang";
        RUSTFLAGS = "-Clink-arg=-fuse-ld=${pkgs.mold}/bin/mold";
      };
    };
}

now if I run cargo run I’m getting the following error message:

  = note: gcc: error: unrecognized command-line option '-fuse-ld=/nix/store/jjgspa8kvy8rgl2fsr6yqyrmiynxl28y-mold-2.3.3/bin/mold'

may I ask what I’m doing wrong?

completely untested, but the following should work

devShells.${system}.default = pkgs.mkShell.override {
  stdenv = pkgs.stdenvAdapters.useMoldLinker pkgs.clangStdenv;
} {
  packages = [ ... ];
};
1 Like

hm… sadly it still doesn’t work

I’m not sure how to translate it to a flake or why I can’t make it work through CARGO_TARGET_<triple>_LINKER env variable but the following works for me.

shell.nix

{ pkgs ? import <nixpkgs> {
  overlays = [
    (import (builtins.fetchTarball "https://github.com/oxalica/rust-overlay/archive/master.tar.gz"))
  ];
} } :
with pkgs;
stdenv.mkDerivation {
  name = "rust-with-mold";
  nativeBuildInputs = [
    rust-bin.stable.latest.default
    mold
    clang
  ];
  RUSTFLAGS = "-Clink-arg=-fuse-ld=${pkgs.mold}/bin/mold";
}

.cargo/config.toml

[target.x86_64-unknown-linux-gnu]
linker = "clang"

hm… I don’t want to use a config file, because I’d like to have multiple rust-shells like one rust-shell with the default settings as a backup-rust-shell.

But I could find a solution (although not really portable):

{
  description = "NixOS configuration";

  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/master";
    rust-overlay.url = "github:oxalica/rust-overlay";
  };

  outputs = { nixpkgs, rust-overlay, ... }:
    let
      system = "x86_64-linux";
      pkgs = import nixpkgs {
        inherit system;

        overlays = [ rust-overlay.overlays.default ];
      };
    in
    {
      devShells.${system}.default = pkgs.mkShell {
        packages = with pkgs; [
          rust-bin.stable.latest.default
        ];

        CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER = "${pkgs.llvmPackages.clangUseLLVM}/bin/clang";
        CARGO_ENCODED_RUSTFLAGS = "-Clink-arg=-fuse-ld=${pkgs.mold}/bin/mold";
      };
    };
}

But this may be easy to solve, by using an if condition to get the suitable target name.

To follow up, this does in fact work, assuming you don’t set override linker flags in a way that breaks what stdenv is already taking care of.