I am quite new to NixOS, and if you’re asking, I did read the manual.
I want a nice guide on how to use nix-shell with Rust, managing Cargo packages, building my programs and other stuff.
Also, share your own workflow if you are a Rust programmer, would be helpful for me to take as an example.
Which manual? Also the Nixpkgs manual with the section on Rust with the section on nix-shell
usage?
Oh, it looks like I only read NixOS 23.11 manual | Nix & NixOS
Guess that’s another manual for me to read.
I followed the guide on the page you linked, worked for building a simple hello world program.
What I want to know now is how can I create a .nix file that when ran using nix-shell will install some packages like carnix, cargo and rustc
Also that particular .nix file ran using nix-shell, what is it called? I’d like to call it by it’s name the next time I mention it.
The simplest shell.nix
for rust would look like
{ pkgs: import <nixpkgs> }:
pkgs.mkShell {
buildInputs = with pkgs; [ cargo carnix ];
}
I think that’ll bring in all the dependencies you’d need. When you start needing outside dependencies (sqlite, openssl, etc) you can add them to that.
For development I mostly use a shell.nix
with the Rust toolchain. I use Mozilla’s Rust overlay because it makes it so easy to get the current stable versions, nightlies, or even specific nightlies (for pyo3
). E.g.
with import <nixpkgs> {};
stdenv.mkDerivation rec {
name = "finalfusion-utils-env";
env = buildEnv { name = name; paths = buildInputs; };
buildInputs = [
latest.rustChannels.stable.rust
}
To make something properly buildable, I add default.nix
using crate2nix
+ buildRustCrate
or buildRustPackage
.
FWIW here’s my shell.nix for rust stuff:
let
# Last updated: 2/26/21. Update as necessary from https://status.nixos.org/...
pkgs = import (fetchTarball("https://github.com/NixOS/nixpkgs/archive/04ac9dcd311956d1756d77f4baf9258392ee7bdd.tar.gz")) {};
# Rolling updates, not deterministic.
# pkgs = import (fetchTarball("channel:nixpkgs-unstable")) {};
in pkgs.mkShell {
buildInputs = [
pkgs.cargo
pkgs.rustc
pkgs.rustfmt
# Necessary for the openssl-sys crate:
pkgs.openssl
pkgs.pkg-config
];
# See https://discourse.nixos.org/t/rust-src-not-found-and-other-misadventures-of-developing-rust-on-nixos/11570/3?u=samuela.
RUST_SRC_PATH = "${pkgs.rust.packages.stable.rustPlatform.rustLibSrc}";
}
Howdy!
My comments are slightly off-topic since they do not constitute a full how-to guide.
I have followed examples on the wiki. These examples demonstrate a few options. But they could also be out-of-date or inaccurate.
Yesterday I learned about another Rust overlay from @oxalica: GitHub - oxalica/rust-overlay: Pure and reproducible nix overlay of binary distributed rust toolchains
This overlay looks incredibly promising because it has precompiled toolchains. I have seen the Mozilla overlay recompile a full toolchain before.
I hope to write a shell.nix
using oxalica’s rust-overlay for another OSS project. I’ll post a link here once I get around to it!
For others looking, it turns out Oxalica’s Rust overlay is very nice, here is a shell.nix
file I use:
{ nixpkgs ? import <nixpkgs> { }}:
let
rustOverlay = builtins.fetchTarball "https://github.com/oxalica/rust-overlay/archive/master.tar.gz";
pinnedPkgs = nixpkgs.fetchFromGitHub {
owner = "NixOS";
repo = "nixpkgs";
rev = "1fe6ed37fd9beb92afe90671c0c2a662a03463dd";
sha256 = "1daa0y3p17shn9gibr321vx8vija6bfsb5zd7h4pxdbbwjkfq8n2";
};
pkgs = import pinnedPkgs {
overlays = [ (import rustOverlay) ];
};
in
pkgs.mkShell {
buildInputs = with pkgs; [
rust-bin.stable.latest.default
rust-analyzer
];
RUST_BACKTRACE = 1;
}
I blogged about a more classic approach too here if anyone is interested.
I’ve been using the Oxalica overlay for my shell for a while.
let
rust_overlay = import (builtins.fetchTarball "https://github.com/oxalica/rust-overlay/archive/master.tar.gz");
cargo2nix = import (builtins.fetchTarball "https://github.com/cargo2nix/cargo2nix/tarball/master") {};
pkgs = import <pkgs-21.05> { overlays = [ rust_overlay ]; };
unstable = import <unstable> {};
rust = pkgs.rust-bin.stable."1.54.0".default.override {
extensions = [ "rust-src" ];
};
in pkgs.mkShell {
name = "luminescent-dreams-core";
buildInputs = [
pkgs.exiftool
pkgs.file
pkgs.pkgconfig
pkgs.glib
pkgs.gtk3
pkgs.wrapGAppsHook
rust
cargo2nix.package
unstable.rust-analyzer
];
shellHook = ''
if [ -e ~/.nixpkgs/shellhook.sh ]; then . ~/.nixpkgs/shellhook.sh; fi
export MAGIC_DB=${pkgs.file}/share/misc/magic.mgc;
'';
}
I was particularly happy when I discovered the extensions = [ "rust-src" ]
statement, which finally got rust-analyzer working reliably.
So, any of you know how to use Oxalica to specify the Rust and Cargo packages for buildRustPackage
? I know that as part of a nixpkgs package, I would just use the default that nixpkgs uses, but my work is internal and I really need to specify a known version in order to stay with my co-workers.
Great question. I do not know off the top of my head.
@savannidgerinel would you be up for posting this as a separate topic? I’m curious if anyone has done this. It also seems like a good question to have for reference on this discourse.
From memory, something like this should work:
let
rust = pkgs.rust-bin.stable."1.54.0".default.override {
extensions = [ "rust-src" ];
};
rustPlatform = pkgs.makeRustPlatform {
cargo = rust;
rustc = rust;
};
in
rustPlatform.buildRustPackage {
...
}