Build a flake package with override

Hey, I’d like to build a package from a flake with an override. Is there a way to do this? Without flakes, I’d do something like the following:

nix build --impure --expr 'with (import ./. {}); foo.override { bar = "something"; }'

This will build the package foo with the specified override and will work great in nixpkgs. However, in a setup where the package that should be overridden is declared in a flake.nix, this won’t work, as the command is looking for a default.nix.

I’ve experimented a bit and got to the following command, which at least gets the derivation attribute, but the build will fail with a weird error:

nix build --impure --expr '(builtins.getFlake (toString ./.)).outputs.legacyPackages.x86_64-linux.foo.override { bar = "something"; }'

Is there a way to archive something similar with flakes?

This seems to work:

{
  description = "A very basic flake";

  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
  };

  outputs =
    { self, nixpkgs }:
    let
      system = "x86_64-linux";
      pkgs = nixpkgs.legacyPackages.${system};

      myPackage =
        {
          blah ? false,
          ...
        }:
        pkgs.stdenv.mkDerivation (
          finalAttrs: {
            pname = "sampleDerivation";
            version = "0.0.1";

            dontUnpack = true;

            buildPhase =

              if (pkgs.lib.traceVal blah) then
                ''
                  mkdir $out
                  echo "blah is true" > $out/foo
                ''
              else
                ''
                  mkdir $out
                  echo "blah is false" > $out/foo
                '';
          }
        );
    in
    {

      packages.${system}.default = pkgs.callPackage myPackage { };
    };
}

And:

❯ nix build --impure --expr '(builtins.getFlake (toString ./.)).outputs.packages.x86_64-linux.default.override { blah = true; }' && cat result/foo
trace: true
blah is true
❯ nix build . && cat result/foo
trace: false
blah is false

Maybe the way .foo is defined in your case causes it to be not overridable?

1 Like

Thanks for verifying! I found the actual problem, it was the --impure flag that caused untracked files being copied into the derivations source and causing weird build failures.

When removing the impure flag, I get the following error

cannot call 'getFlake' on unlocked flake reference '/home/katexochen/foo', at «none»:0 (use --impure to override)

Not sure if there is also a way to load the local flake including the lock file, so this could be done without needing to build impure?

Assuming you are using git to track the flake files, you could try to pass a specific revision to builtins.getFlake which will get rid of untracked files:

❯ git log                                                          
commit 4a8548065a61980793a242f1e003c4c2c43a466f (HEAD -> master)
Author: Me
Date:   Thu Mar 14 08:04:30 2024 -0700

    init

❯ nix build --expr "(builtins.getFlake \"git+file://$(pwd)?rev=4a8548065a61980793a242f1e003c4c2c43a466f\").outputs.packages.x86_64-linux.default.override { blah = true; }" && cat result/foo
trace: true
blah is true
1 Like

Yes, that did it, thanks a lot!