我想运行一个安装了以下软件包的 nix-shell:
我不能简单地做:nix-shell -p aspell aspellDicts.en hello --pure因为这将无法正确安装 aspell 词典。Nix 提供了一个aspellWithDict函数,可用于使用字典构建 aspell:
nix-build -E 'with import <nixpkgs> {}; aspellWithDicts (d: [d.en])'
Run Code Online (Sandbox Code Playgroud)
我想将此构建的结果用作另一个本地包 (foo) 中的依赖项。这就是我目前实现这一目标的方式:
./pkgs/aspell-with-dicts/default.nix:
with import <nixpkgs> {};
aspellWithDicts (d: [d.en])
Run Code Online (Sandbox Code Playgroud)
./pkgs/foo/default.nix:
{stdenv, aspellWithDicts, hello}:
stdenv.mkDerivation rec {
name = "foo";
buildInputs = [ aspellWithDicts hello ];
}
Run Code Online (Sandbox Code Playgroud)
./custom-packages.nix:
{ system ? builtins.currentSystem }:
let
pkgs = import <nixpkgs> { inherit system; };
in
rec {
aspellWithDicts = import ./pkgs/aspell-with-dicts;
foo = import ./pkgs/foo {
aspellWithDicts = aspellWithDicts;
hello = pkgs.hello;
stdenv = pkgs.stdenv;
};
}
Run Code Online (Sandbox Code Playgroud)
运行 shell 按预期工作: nix-shell ./custom-packages.nix -A foo --pure
所以我的解决方案有效,但是这个结果可以以更简洁的惯用方式实现吗?
为了使这段代码更加地道,我有以下建议:
callPackage使用该pkgs.callPackage功能。它将负责传递您的推导所需的参数。这就是为什么 NixPkgs 中的许多文件看起来像{ dependency, ...}: something. 第一个参数是您想要注入依赖项的函数,第二个参数是一个属性集,您可以使用它手动传递一些依赖项。
通过使用callPackage,您不需要这样做import <nixpkgs> {},因此您的代码将更容易在<nixpkgs>无法使用的新上下文中使用,并且评估速度会更快一些,因为它只需评估 NixPkgs 固定点一次。
(当然,你必须import <nixpkgs>先开始一次,但之后就没有必要了。)
with在pkgs/aspell-with-dicts/default.nix您使用with关键字时,这是可以的,但在这种情况下它并没有真正增加价值。我更喜欢明确地引用变量,因此更喜欢pkgs.something在使用一次或两次时或者inherit (pkgs) something使用更频繁时阅读。这样读者可以很容易地确定变量来自哪里。
当尝试不熟悉的软件包或功能时,我确实会使用它,因为那时维护就不是问题了。
pkgs/aspell-with-dicts/default.nix除非您期望 aspell 的实例化是您想要重用的东西,否则在您使用它的地方构建它可能会更容易。
如果您确实希望重用包的特定配置,您可能希望通过在覆盖层中构造它来使其成为一流包。
就是这样。我认为最重要的一点是避免<nixpkgs>,除此之外它已经很惯用了。
我不知道你的神秘foo是什么,但如果它是开源的,请考虑将其上游到 NixPkgs 中。根据我的经验,尼克斯有一个非常热情的社区。
| 归档时间: |
|
| 查看次数: |
2071 次 |
| 最近记录: |