Hi!
I’d like to build a project without having to copy it to the nix store, to avoid the extra copy time and the space build-up.
I can do it by using --sandbox-paths
and get the right caching behavior (i.e. it rebuilds only when the project changes) by putting a content hash of the project as input of the derivation. E.g. something like this (the hello file representing the project):
echo Hello > hello
nix --sandbox-paths /source/"$(nix hash file --base16 --type sha256 hello)"=./hello build --expr '
let pkgs = (import <nixpkgs>) {system = "x86_64-linux";};
storep = "/source/'"$(nix hash file --base16 --type sha256 hello)"'";
in pkgs.runCommand "test" {} "cat ${storep} > $out; echo ${storep} >> $out"
' --impure
Of course the drawback is that you lose some of the reproducibility and hermeticity.
So I thought maybe I could use a fixed output derivation as the target of the sandbox path instead, that way it could work with and without sandbox path. Unfortunately nix builds the derivation and shadows the sandbox path.
echo Hello > hello
nix hash file --type sha256 hello
# sha256-ZqBFtFIQLFnYQOwJfVnZRn4To/NPZJTlOf/TLBuzXxg=
nix --sandbox-paths /nix/store/41p2c0yfh3idhwxsmj45ca2lymkcs9np-source=./hello build --expr '
let pkgs = (import <nixpkgs>) {system = "x86_64-linux";};
storep = "${pkgs.runCommand "source" { outputHashMode = "flat"; outputHashAlgo = "sha256"; outputHash = "sha256-ZqBFtFIQLFnYQOwJfVnZRn4To/NPZJTlOf/TLBuzXxg="; } "echo Hello > $out"}";
in pkgs.runCommand "test" {} "cat ${storep} > $out; echo ${storep} >> $out"
' --impure
# Should build without --sandbox-paths too
nix build --expr '
let pkgs = (import <nixpkgs>) {system = "x86_64-linux";};
storep = "${pkgs.runCommand "source" { outputHashMode = "flat"; outputHashAlgo = "sha256"; outputHash = "sha256-ZqBFtFIQLFnYQOwJfVnZRn4To/NPZJTlOf/TLBuzXxg="; } "echo Hello > $out"}";
in pkgs.runCommand "test" {} "cat ${storep} > $out; echo ${storep} >> $out"
' --impure
I can kind of get it to work if I do some string manipulation on the fixed output derivation store path, I guess it removes the context on the string so nix doesn’t know it should build that path:
nix --sandbox-paths /nix/store/41p2c0yfh3idhwxsmj45ca2lymkcs9np-source=./hello build --expr '
let pkgs = (import <nixpkgs>) {system = "x86_64-linux";};
storep = "/nix/store/" + (builtins.elemAt (builtins.split "/nix/store/" "${pkgs.runCommand "source" { outputHashMode = "flat"; outputHashAlgo = "sha256"; outputHash = "sha256-ZqBFtFIQLFnYQOwJfVnZRn4To/NPZJTlOf/TLBuzXxg="; } "echo Hello > $out"}") 2);
in pkgs.runCommand "test" {} "cat ${storep} > $out; echo ${storep} >> $out"
' --impure
But then this doesn’t work without sandbox-paths, so it’s no better than the first solution:
$ nix build --expr '
let pkgs = (import <nixpkgs>) {system = "x86_64-linux";};
storep = "/nix/store/" + (builtins.elemAt (builtins.split "/nix/store/" "${pkgs.runCommand "source" { outputHashMode = "flat"; outputHashAlgo = "sha256"; outputHash = "sha256-ZqBFtFIQLFnYQOwJfVnZRn4To/NPZJTlOf/TLBuzXxg="; } "echo Hello > $out"}") 2);
in pkgs.runCommand "test" {} "cat ${storep} > $out; echo ${storep} >> $out"
' --impure
error: builder for '/nix/store/w3q2nhkl18wgkmqbgn6dpzri309w8168-test.drv' failed with exit code 1;
last 1 log lines:
> cat: /nix/store/41p2c0yfh3idhwxsmj45ca2lymkcs9np-source: No such file or directory
For full logs, run 'nix log /nix/store/w3q2nhkl18wgkmqbgn6dpzri309w8168-test.drv'.
I wonder if it’s something that should work? The documentation doesn’t say what should happen when you do this. It could be pretty handy especially with the git-hashing feature as you can compute the nix store path of a git repo from just git rev-parse HEAD:
.
Just some thoughts, for now I’ll use the first solution for my use-case!