Nix Pill 14:如何使 callPackage 可覆盖?
Nix Pill 14: How to make callPackage overridable?
我无法理解 Nix Pill 14。作者提供makeOverridable
,然后挑战用户将其与callPackage
集成。提供makeOverridable
和default.nix
,如下,其中makeOverridable
在文件lib.nix
中,callPackage
在文件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
这是我想出的:
# 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
我想我对这里发生的事情有根本的误解。你能提供正确的实现并解释我做错了什么吗?
编辑:我设法让它工作,但是,它仍然不是递归的。
# 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
编辑 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
解决方案:
# 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
如果使用 Nix Pills 中的定义之一正确定义 makeOverridable
,您可以将其视为高阶函数:它采用名为 f
的普通函数,并且它会更改它变成一个新函数,其结果可以被覆盖。
假设您已经有一个名为 callPackage1
的函数,您可以像这样制作一个可覆盖的版本:
rec {
callPackage1 = ...;
callPackage = makeOverridable callPackage1;
}
编辑 1:
实际上,callPackage1
需要一条路径才能 return makeOverridable
所期望的函数类型(一个接受集合和 returns 的函数我们可以向其添加覆盖 attribute
) 的对象。那么让我们试试这个 callPackage
:
的定义
callPackage = path: makeOverridable (callPackage1 path);
我正在使用相同的 Nix Pills,但在 Pill 14 的 reader 练习中遇到了问题。我发现这里的答案很有帮助。
在我的解决方案中,makeOverridable 的参数是一个未命名的函数。
let
nixpkgs = import <nixpkgs> {};
allPkgs = nixpkgs // pkgs;
lib = import ./lib.nix;
# Function to find arguments of function defined in "path"
callPackage = path: lib.makeOverridable (overrides:
{ result =
let f = import path;
in f (
(builtins.intersectAttrs (builtins.functionArgs f) allPkgs)
// overrides
); }) {};
pkgs = with nixpkgs; rec {
mkDerivation = import ./autotools.nix nixpkgs;
hello = callPackage ./hello.nix;
graphviz = callPackage ./graphviz.nix;
graphvizCore = graphviz.override { gdSupport = false; };
};
in pkgs
我无法理解 Nix Pill 14。作者提供makeOverridable
,然后挑战用户将其与callPackage
集成。提供makeOverridable
和default.nix
,如下,其中makeOverridable
在文件lib.nix
中,callPackage
在文件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
这是我想出的:
# 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
我想我对这里发生的事情有根本的误解。你能提供正确的实现并解释我做错了什么吗?
编辑:我设法让它工作,但是,它仍然不是递归的。
# 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
编辑 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
解决方案:
# 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
如果使用 Nix Pills 中的定义之一正确定义 makeOverridable
,您可以将其视为高阶函数:它采用名为 f
的普通函数,并且它会更改它变成一个新函数,其结果可以被覆盖。
假设您已经有一个名为 callPackage1
的函数,您可以像这样制作一个可覆盖的版本:
rec {
callPackage1 = ...;
callPackage = makeOverridable callPackage1;
}
编辑 1:
实际上,callPackage1
需要一条路径才能 return makeOverridable
所期望的函数类型(一个接受集合和 returns 的函数我们可以向其添加覆盖 attribute
) 的对象。那么让我们试试这个 callPackage
:
callPackage = path: makeOverridable (callPackage1 path);
我正在使用相同的 Nix Pills,但在 Pill 14 的 reader 练习中遇到了问题。我发现这里的答案很有帮助。
在我的解决方案中,makeOverridable 的参数是一个未命名的函数。
let
nixpkgs = import <nixpkgs> {};
allPkgs = nixpkgs // pkgs;
lib = import ./lib.nix;
# Function to find arguments of function defined in "path"
callPackage = path: lib.makeOverridable (overrides:
{ result =
let f = import path;
in f (
(builtins.intersectAttrs (builtins.functionArgs f) allPkgs)
// overrides
); }) {};
pkgs = with nixpkgs; rec {
mkDerivation = import ./autotools.nix nixpkgs;
hello = callPackage ./hello.nix;
graphviz = callPackage ./graphviz.nix;
graphvizCore = graphviz.override { gdSupport = false; };
};
in pkgs