Hacker News new | ask | show | jobs
by tikhonj 1990 days ago
> Using a special command (nix-shell) whenever I needed to do development things (e.g. Rust builds) was not my idea of fun.

Funny you should mention that, because that's exactly what got me using Nix everywhere :). I've always hated installing tools and libraries globally—what if I need a different version for a future project?—so I like tools that sandbox as much as possible like virtualenv, cargo, cabal... etc. But these tools are all language-specific and have their own limitations (especially around native libraries and dependencies written in other languages).

nix-shell gives me the equivalent of virtualenv that works for everything. I can have a single sandboxed environment even if my project uses a bunch of different languages and I can manage everything in a reproducible, low-overhead fashion. No more worrying about making a mess by installing tools or packages globally.

Then, once I got really used to that, I spent some time setting up direnv[1] and lorri[2]—both of which are themselves managed with Nix, of course!—so that my environment gets automatically configured as soon as I enter a project directory without needing to call nix-shell explicitly. To be honest, the experience is still a bit rough, but it works well enough day-to-day that I have my reproducible sandbox cake and eat it in an mostly frictionless way too :).

[1]: https://direnv.net/

[2]: https://github.com/target/lorri

2 comments

Exactly. direnv/lorri basically solves the per-language virtualenv nonsense, but universally for anything. I use chezmoi to manage my shell.nix for various directories. That way every project can manage its system libraries independently. Once you get used to it, it's truly amazing. So much so, I almost think the future trend, once enough people become enlightened, will be checking in shell.nix as standard for development projects.
Out of interest, how does this work if using something like Visual Studio Code or some other IDE?
I've had sufficient success cd'ing into the project directory, activating my nix-shell, and then launching VS Code from inside that shell. In which case it inherits the shell's environment and most things work as expected.

There's surely a better way to do it, but I tend to prefer vim + lots of terminals over VS Code, so I haven't looked too closely at that workflow.

I use Emacs's direnv integration. Haven't had any trouble. It straight-up works better than alternatives I tried before like trying to turn pyvenv mode on automatically.

I also manage Emacs, its packages and its packages' native dependencies with Nix.

Having an automatic link between Emacs packages and native libraries has made my life massively easier. For example, earlier today I installed `pdf-tools`[1] just by adding (use-package pdf-tools :ensure t) to my init.el, and Nix took care of building and installing the native software needed to support it. I didn't have to go through any of the installation steps in the pdf-tools README[1], it just worked.

I'm on my laptop now, but when I get back to my desktop, all it will take to get pdf-tools working is pulling the latest version of my config from git and switching to it. As long as there's a version of the native libraries packaged for macOS, getting it working on my work laptop won't be any harder; if there aren't, I might either change the config to only have that package on Linux or I might write a bit of Nix code myself to build a macOS-compatible version.

pdf-tools is a cute self-contained example, but this has been even bigger for using lsp-mode and different language servers as well as other nice-to-have development tools.

For all the hassle that learning and moving to NixOS took—and still occasionally takes—I'm convinced that things like this have more than paid off for me and that I'm saving time on net.

[1]: https://github.com/politza/pdf-tools

Not who you're replying to, but I just launch the IDE from the shell. e.g. for running qtcreator:

  nix-shell -p qtcreator qt5Full gnumake gcc gdb cmake
If I need other libraries in there, I can add them to it. I don't use direnv/lorri, but I assume you would have to relaunch the IDE in the case of adding more dependencies, unless the IDE has nix-shell integration (like an emacs user mentions in a sibling comment).

I made a different way of setting up a development environment[1] that would probably work just as well for e.g. VSCode, that doesn't require restarting the IDE. I did this for lisp development, where dynamically loading libraries during development is fairly idiomatic; it took me about 15 minutes to write, and could probably be adapted for other IDEs as well.

1: https://git.sr.ht/~jasom/nix-lisp-dev/tree

edit: this is how my vscode is configured using nix on top of Xubuntu:

vscode is installed globally using the buildEnv-based declarative user environment approach (https://gist.github.com/lheckemann/402e61e8e53f136f239ecd8c1...). Then in individual projects I include language-specific dependencies such as dotnet-sdk_3 or google-cloud-sdk.