The Linux Cast - Is nixos over hyped

Depends what you exactly put into the word “debugging”. So there exists some tools like breakpointHook to move you into the VM where the derivation failed, but what I had in mind is a bit different (breakpointHook will still ask you to recompile everything from scratch everytime you change the derivation without caching anything), and follows the proof of concept I gave here. So usually, one way to manually test a compilation workflow (while benefiting from previously cached tries), is to run:

$ nix-shell
$ export out=/tmp/out
$ source $stdenv/setup
$ export NIX_ENFORCE_PURITY=0
$ set +e
$ genericBuild

or, if you want to run only a specific phase, run phases="buildPhase" genericBuild. It does work reasonably well, but is not super handy to use:

  1. you need to type like 5 lines just to start debugging
  2. it will only work in bash shell, unless you nest shells like zsh > bash > zsh (but then you need to type all compilation commands manually).
  3. it is your role of knowing which command/phase to run, where to extract the source… if phase A sets a variable used in phase B, you need to be sure to run it.
  4. some phases might not be idempotent (like patch phase, source extraction that expects an empty folder), so usually you don’t want to run these phases twice: so you need to know which phase is safe to run twice, which phase is not safe, which phase has been run already, which environment was configured at the end of which phase…
  5. if you change the .nix derivation, you need to restart everything to take it into account
  6. for some reasons, the shell often exists by itself (e.g. if the compilation command contains a exit 1 due to an error), which is extremely annoying when debugging
  7. it will not help you to write basic templates (if I have a simple python code, I’d like to automatically generate the derivation semi-automatically)

Direnv does make it slightly nicer to use, but it is also not completely trivial. One possibility to make it nicer to use is to create a simple wrapper around these commands, which is exactly what I did here, so nothing super fancy, just a time saver. But it would be nice to make it a bit more cleaver, for instance to automatically restart the shell if new derivations are added etc. Some random ideas I had:

  1. it could be cool to automatically restart the shell if the derivation is changed (that is quite nicely done by direnv right now)
  2. try to see automatically which phase to run depending on the phase previously run, possibly saving the environment/bash commands defined in a file, and saving the state of source before/after running a given command (this way you can run the patch phase in a copy of the source, and copy this back to the working directory to still benefit from cached builds).
  3. define a command like nix help-me-write-derivation that could try to automatically write a basic derivation, possibly by asking the user about the preferred setup :
> I see you have a single python script in your project, will your project
1) stay with a simple python script to run
2) turn into a more complex project that provides python libraries (this will create a setup.py file)
1
> After looking at the python script, I see that you import numpy and requests. Do you want to add other dependencies? Which one?
foo
> I can see that foo is not packaged in nixpkgs. Would you like instead to use dream2nix? [y/n]
y
… 

Another really cool thing to have could be to have incremental pure builds, in the sense that if the build phase is successful but not the install phase (this occurs REALLY often), I would like the next build to automatically restart from the end of the build phase rather than restarting from scratch. But this involve changes directly on nix-side I guess, and saving all bash environments + functions (using maybe env and declare -f like here), so I don’t really know how easy it would be to achieve that in a highly pure way.

Anyway, my point is to say that I think nix could provide a nicer user interface to build stuff.

5 Likes