Nix pattern: run command to generate nix value

I find useful to generate data with a external command to be consumed in a derivation, something like this:

let 
  foo' = runCommand "foo" "somecmd arg1 arg2 > $out";
  foo = builtins.fromJSON (builtins.readFile foo');
in stdenv.mkDerivation {
  # We use foo here
}

My idea here is to leverage some external command to simplify the derivation. Sometimes is too difficult to do something in pure nix, but with an external utility is just one command away.

I’d like to know what do you think about this pattern, or if you can think of a better alternative.

Not sure, but since I didn’t find a similar approach in the wild, I fear that I’m missing some potential problem with it.

2 Likes

This approach is known as “import from derivation” and considered an antipattern, which will even be disabled by default in future versions of nix.

3 Likes

I think builtins.exec is intended to do what you’re trying to do. It’s basically a FFI for Nix: it allows you to call an external command that returns a Nix expression.
Of course it’s neither safe nor pure, but you know what you’re doing I guess it may be fine.

For obvious reasons it’s disabled by default: you need to set the Nix option allow-unsafe-native-code-during-evaluation to use it.

3 Likes

The alternative is the approach various 2nix projects take; generate the JSON with that command before the build, and commit it to your repository.

That way the impurity becomes part of the source, and is no longer impure and potentially host-dependent, so your build is once again reproducible.

The downside is that this takes a bit more maintenance effort. The ideal is to avoid situations in which this is necessary in the first place, but that’s not always feasible (e.g., when trying to use any npm package, because you simply cannot write custom build scripts for hundreds of JavaScript packages that normally expect to download their dependencies…).

I wonder if there could be some sort of way to define what auxilliary scripts sometimes need to be run in flakes that would help with the maintenance of things like this.

3 Likes