I am having trouble understanding Nix Pill 14. The author provides makeOverridable
, and then challenges the user to integrate it with callPackage
. makeOverridable
and default.nix
are provided, as follows, where makeOverridable
is in the file lib.nix
, and callPackage
is in the file default.nix
:
# file: lib.nix
rec {
makeOverridable = f: origArgs:
let
origRes = f origArgs;
in
origRes // { override = newArgs: makeOverridable f (origArgs // newArgs); };
}
# file: default.nix
let
nixpkgs = import <nixpkgs> {};
allPkgs = nixpkgs // pkgs;
callPackage = path: overrides:
let f = import path;
in f ((builtins.intersectAttrs (builtins.functionArgs f) allPkgs) // overrides);
pkgs = with nixpkgs; {
mkDerivation = import ./autotools.nix nixpkgs;
hello = callPackage ./hello.nix { };
graphviz = callPackage ./graphviz.nix { };
graphvizCore = callPackage ./graphviz.nix { gdSupport = false; };
};
in pkgs
This is what I have come up with:
# file: default.nix (my implementation)
let
nixpkgs = import <nixpkgs> {};
allPkgs = nixpkgs // pkgs;
callPackage = path: overrides:
let
f = import path;
origRes = f ((builtins.intersectAttrs (builtins.functionArgs f) allPkgs) // overrides);
in
origRes // { override = newArgs: callPackage f (overrides // newArgs); };
pkgs = with nixpkgs; {
mkDerivation = import ./autotools.nix nixpkgs;
hello = import ./hello.nix {};
graphviz = import ./graphviz.nix {};
graphvizCore = graphviz.override { gdSupport = false; };
};
in pkgs
I think I have a fundamental misunderstanding of what is going on here. Could you please provide the correct implementation and explain what I am doing wrong?
EDIT: I managed to get it to work, however, it is still not recursive.
# file: default.nix
let
nixpkgs = import <nixpkgs> {};
allPkgs = nixpkgs // pkgs;
callPackage = path: overrides:
let
f = import path;
origArgs = f ((builtins.intersectAttrs (builtins.functionArgs f) allPkgs) // overrides);
makeOverridable = { override = newArgs: (origArgs // newArgs); };
in
origArgs // makeOverridable;
pkgs = with nixpkgs; rec {
mkDerivation = import ./autotools.nix nixpkgs;
hello = callPackage ./hello.nix { };
graphviz = callPackage ./graphviz.nix { };
graphvizCore = graphviz.override { gdSupport = false; };
};
in pkgs
EDIT 2:
# file: default.nix
let
nixpkgs = import <nixpkgs> {};
allPkgs = nixpkgs // pkgs;
makeOverridable = f: origArgs:
let origRes = f origArgs;
in origRes // { override = newArgs: makeOverridable f (origArgs // newArgs); };
callPackage1 = path: overrides:
let f = import path;
in f ((builtins.intersectAttrs (builtins.functionArgs f) allPkgs) // overrides);
callPackage = makeOverridable callPackage1;
pkgs = with nixpkgs; {
mkDerivation = import ./autotools.nix nixpkgs;
hello = callPackage ./hello.nix { };
graphviz = callPackage ./graphviz.nix { };
graphvizCore = graphviz.override { gdSupport = false; };
};
in pkgs
SOLUTION:
# file: default.nix
let
nixpkgs = import <nixpkgs> {};
allPkgs = nixpkgs // pkgs;
makeOverridable = f: origArgs:
let origRes = f origArgs;
in origRes // { override = newArgs: makeOverridable f (origArgs // newArgs); };
callPackage1 = path: overrides:
let f = import path;
in f ((builtins.intersectAttrs (builtins.functionArgs f) allPkgs) // overrides);
callPackage = path: makeOverridable (callPackage1 path);
pkgs = with nixpkgs; rec {
mkDerivation = import ./autotools.nix nixpkgs;
hello = callPackage ./hello.nix { };
local_graphviz = callPackage ./graphviz.nix { };
graphvizCore = local_graphviz.override { gdSupport = false; };
graphvizCore2 = graphvizCore.override { gdSupport = false; };
};
in pkgs
If makeOverridable
is defined properly using one of the definitions in Nix Pills, you can think of it as a higher-order function: it takes a normal function named f
, and it changes it into a new function whose results can be overridden.
Assuming you already have a function named callPackage1
, you can make an overridable version like this:
rec {
callPackage1 = ...;
callPackage = makeOverridable callPackage1;
}
EDIT 1:
Actually, callPackage1
needs a path in order to return the type of function that is expected by makeOverridable
(a function that takes a set and returns an object to which we can add the override attribute
). So let's try this definition of callPackage
:
callPackage = path: makeOverridable (callPackage1 path);