Rust IntelliJ Toolchain setup

I was figuring out how to setup a Nix, Rust & IntelliJ setup.
At the moment this setup does not use the Mozilla overlay.

derivation.nix

{ stdenv, rustPlatform, lib, ... }:
rustPlatform.buildRustPackage rec {
  pname = "example";
  version = "0.1.0";

  # clean source is super important so that the path names are consistent
  # across machines
  src = lib.cleanSource ./.;

  buildInputs = [ ];

  cargoSha256 = "13gxfrc7vxhf32y0vcp8x6rcjxc1hsq81qj1l4p9qrj7899k617y";
  verifyCargoDeps = true;

  meta = with stdenv.lib; {
    description = "My example project";
    homepage = "https://example.org/my-project";
    license = licenses.mit;
    platforms = platforms.linux;
    maintainers = [ "you@you.com" ];
  };
}

overlay

self: super:
{
	# make our package installable easily to minimize the default.nix file
	example = self.callPackage ./derivation.nix { };
}

default.nix

let
  nixpkgs =
    import <nixpkgs> { overlays = [ (import ./overlay.nix) ]; };
in nixpkgs.example

shell.nix

let
  pkgs =
    import <nixpkgs> {};
  rust-toolchain = pkgs.symlinkJoin {
    name = "rust-toolchain";
    paths = [pkgs.rustc pkgs.cargo pkgs.rustPlatform.rustcSrc];
  };
in with pkgs;
mkShell {
  name = "scriptr";
  buildInputs = [rust-toolchain evcxr rustracer];
  RUST_BACKTRACE = 1;
}

The interesting part is rust-toolchain which I create a symlinkJoin to include cargo & rustc into a single output directory – this was needed by IntelliJ.

I also figured out the Rust SRC path by just seeing what racer was set to.

cat $(which racer)
#! /nix/store/c4wxsn4jays9j31y5z9f83nr2cp7l4pa-bash-4.4-p23/bin/bash -e
export RUST_SRC_PATH=${RUST_SRC_PATH-'/nix/store/26m4ly4dvc6yy0r8wsnyq25g9ng4rasi-rust-src'}
exec -a "$0" "/nix/store/br667jnfmmx38az6rk8aib3jdbqbfr10-racer-2.1.33/bin/.racer-wrapped"  "$@"

Please share if you have improvements to this setup.

7 Likes

No improvements but I just want to add that QtCreator works reasonably well as a debugger for Rust (if someone is looking for a performant solution)

Instructions from here:

https://www.reddit.com/r/rust/comments/a8pfaw/fyi_new_rust_ide_with_proper_debugging/

Build directory: . (literal period)

build:

prog: cargo
arg: build
wd: %{buildDir}

clean:
prog: cargo
arg: clean
wd: %{buildDir}

run/debug:
Executable: target/debug/%{CurrentProject:FileBaseName}
wd: %{buildDir}

Current configuration runs with: (Anything that starts after core shows a lot of time in Stats, don’t worry, it’s actually before that thing not in that thing, notice the angle brackets)

Invocation command:

qtcreator . -noload GLSLEditor -noload ClangTools -noload QmlDesigner -noload QmlJSEditor -noload QmlJSTools -noload Valgrind -noload Python -noload Designer -noload ModelEditor -noload QmakeProjectManager -noload CMakeProjectManager -noload Macros -noload Android -noload ClangCodeModel -noload Subversion -noload QmlProfiler -noload QmlPreview -noload QmlProjectManager -noload VcsBase -noload Qnx -noload Welcome -noload ClassView -noload TaskList -noload CppEditor -noload LanguageClient -noload Help -noload Bookmarks -noload CtfVisualizer -noload PerfProfiler -noload ImageViewer -noload ScxmlEditor -profile

It cold-starts in maybe 3 seconds on my 6 year old machine and takes all of 100 MB.

It could also be used for development but I couldn’t get my language server working (year old story, don’t know what changed since rust-analyzer) and after a while didn’t feel the need.

Hey guys,

I’m not an intellij user myself, but I was debugging some nix integration issue for a friend.

The Rust plugin will actually check your $PATH and see if any of the entries contain as “toolchain”: https://github.com/intellij-rust/intellij-rust/blob/b0047b0ac3996edf22d82ce1aae988fcf0be0082/src/main/kotlin/org/rust/cargo/toolchain/RustToolchain.kt#L203

as @fzakaria mentioned, a toolchain is any directory that contains both rustc and cargo: https://github.com/intellij-rust/intellij-rust/blob/b0047b0ac3996edf22d82ce1aae988fcf0be0082/src/main/kotlin/org/rust/cargo/toolchain/RustToolchain.kt#L25-L26

So basically, add your symlinkJoin to your $PATH and the plugin will autodetect it (make sure you don’t have a ~/.cargo/bin with rustc and cargo, otherwise this will take precedence: https://github.com/intellij-rust/intellij-rust/blob/b0047b0ac3996edf22d82ce1aae988fcf0be0082/src/main/kotlin/org/rust/cargo/toolchain/RustToolchain.kt#L202 )

1 Like

Just start intellij from the command line within your nix shell directory and it’ll inherit the PATH appropriately.

Thanks for your help, this is still useful info:

put something like this in shell.nix (no need for overlays now? Nixpkgs has a valid Rust toolchain available)

let
  pkgs =
    import <nixpkgs> {};
  rust-toolchain = pkgs.symlinkJoin {
    name = "rust-toolchain";
    paths = [pkgs.rustc pkgs.cargo pkgs.rustPlatform.rustcSrc];
  };
in with pkgs;
mkShell {
  name = "scriptr";
  buildInputs = [rust-toolchain];
  RUST_BACKTRACE = 1;
}

Then start idea-community . with the Nix shell active.

IDEA will pester you to configure a Rust toolchain (or visit Settings → Rust)
IDEA will suggest the toolchain location in the drop-down on the path selection box; choose that.

For the stdlib sources, copy the same path but remove the /bin suffix.
Hope this helps someone else e.g. if they’re also coming here by search engine

2 Likes

I kept running into “OS error” until I copied the standard library outside of nix store, it seems that the issue is being addressed on IntelliJ’s plugin side: stdlib is not added to a project dependencies if rust toolchain installed to read-only location (e.g. Nix store) · Issue #7912 · intellij-rust/intellij-rust · GitHub
But the root cause seems to be in rust-lang: https://github.com/rust-lang/cargo/issues/10096

My ugly workaround:

    shellHook = ''
      rsync \
        --recursive \
        --delete \
        --copy-links \
        --perms \
        --chmod=ugo=rwX \
        $(rustc --print sysroot)/lib/rustlib/src/rust/ \
        .rust-std
      '';

Then use .rust-std as path for my “standard library” in IntelliJ.

3 Likes