Is there any way to say "build this derivation but ignore any existing outputs"?

I don’t run with the sandbox enabled normally (on darwin), but I’d prefer to enable it when building packages I’m submitting PRs for. Unfortunately I usually forget, which means I now have a cached output and therefore it won’t rebuild.

I think I can use nix-build --check to rebuild, except A) this requires the outputs to exist already so it will fail if I didn’t build it previously, and B) I’m not sure if I can use this when I need to rebuild sub-derivations as well (e.g. when building ffsend I want to rebuild ffsend.cargoDeps too).

Is there any way of saying “do a build, but ignore any existing outputs for the listed attribute paths”? I obviously can’t say “ignore any existing output” because I don’t want to rebuild my build inputs or the whole stdenv. I also don’t want to outright delete the paths from my store first because that’s both awkward and it can’t be done if I’m using any of these paths in my environment.

2 Likes

Maybe not exactly what you are looking for but you could explicitly delete all outputs that you want to rebuild:nix-store --delete <path>

Yes, I can run something like nix-store --delete $(nix-store -q $(nix-instantiate --quiet -A foo -A foo.cargoDeps .)) to delete the outputs first, but as I said, besides the awkwardness, this is a nonstarter if I’m already using any of these outputs in my environment.

I’ve got this fish shell alias which does what you want. It builds the same derivation but injects some randomness, so that nix thinks it’s somethings new and rebuild it.
Someone suggested it somewhere but I don’t remember who:

# Guarantee to re-build a nix-expression, even if a build result is already in
# the cache or available with a substituter. Useful to debug transient issues.
# Better than `--check` because it also works when there is no version in the
# store yet and it won't complain about non-reproducibility.
function nix-rebuild
  set expression "with (import ./. {}); $argv[1].overrideAttrs (old: { REBUILD_MARKER="(random)"; })"
  echo "Building '$expression'"
  nix-build -E "$expression"
end
2 Likes

I noticed a similar function specifically for Haskell packages:

I guess it would be nice if there was a function to do the same for a stdenv.mkDerivation derivation.

Here’s the same script in bash: https://github.com/timokau/dotfiles/blob/7f273553d8eb912cb2454a9b35f525876901890e/scripts/bin/nix-rebuild

1 Like

I have considered injecting randomness like that, though it won’t rebuild sub-derivations. I’m thinking here of how rust packages have cargoDeps, though that doesn’t really need to rebuilt (it just contains all of the downloaded cargo-vendor sources, not compiled output), but perhaps for a bundlerApp one it would matter because the derivation there is a very thin wrapper around a sub-derivation and just symlinks in the appropriate binaries.

Of course, any such “real” solution would need to know the details of the sub-derivations anyway, though with the bundlerApp version I don’t think there’s any direct access to it, which makes it rather difficult.

I guess my ideal solution would actually be “check the position of the meta on each derivation, if it was defined in this file/folder then we should rebuild the derivation, otherwise we can reuse cached output / substitutes”.