撰写本地nix包

时间:2017-12-01 10:42:32

标签: nix nixos

我想运行安装了以下软件包的nix-shell:

  • 的aspell
  • aspellDicts.en
  • 你好

我不能简单地执行:nix-shell -p aspell aspellDicts.en hello --pure因为这将无法正确安装aspell词典。 Nix提供了一个aspellWithDict函数,可用于构建带有字典的aspell:

nix-build -E 'with import <nixpkgs> {}; aspellWithDicts (d: [d.en])'

我想将此构建的结果用作另一个本地包(foo)中的依赖项。这就是我目前实现这一目标的方式:

./ PKGS /的aspell与 - 类型的字典/ default.nix:

with import <nixpkgs> {};

aspellWithDicts (d: [d.en])

./ PKGS /富/ default.nix:

{stdenv, aspellWithDicts, hello}:

stdenv.mkDerivation rec {
    name = "foo";
    buildInputs = [ aspellWithDicts hello ];
}

./定制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;
  };
}

运行shell按预期工作:nix-shell ./custom-packages.nix -A foo --pure

所以我的解决方案有效,但这种结果能否以更简洁的惯用方式实现?

2 个答案:

答案 0 :(得分:1)

您需要构建foo吗?您将使用foo中的内容?

假设您只想通过nix-shell使用shell,而不想使用nix-buildnix-env -i来构建/安装任何内容,这应该可行。

以下shell.nix

with import <nixpkgs> {};
with pkgs;

let
  myAspell = aspellWithDicts (d: [d.en]);
in
  stdenv.mkDerivation {
    name = "myShell";

    buildInputs = [myAspell hello];

    shellHooks = ''
      echo Im in $name.
      echo aspell is locate at ${myAspell}
      echo hello is locate at ${hello}
    '';
  }

将为您提供包含aspellhello

的shell
$ nix-shell
Im in myShell.
aspell is locate at /nix/store/zcclppbibcg4nfkis6zqml8cnrlnx00b-aspell-env
hello is locate at /nix/store/gas2p68jqbzgb7zr96y5nc8j7nk61kkk-hello-2.10

如果foo有一些代码需要构建和安装。

mkDerivation中的

foo/default.nix必须包含src字段src = ./.;或类似fetchurlfetchFromGithub的字段(请参阅document例如)。

然后您可以使用callPackagesimport(取决于编写nix表达式的方式)和foo/default.nix作为参数来提供在此shell中使用的foo

如果您尝试构建此shell.nix(或foo/default.nix),则会失败并失去src

$ nix-build shell.nix 
these derivations will be built:
  /nix/store/20h8cva19irq8vn39i72j8iz40ivijhr-myShell.drv
building path(s) ‘/nix/store/r1f6qpxz91h5jkj7hzrmaymmzi9h1yml-myShell’
unpacking sources
variable $src or $srcs should point to the source
builder for ‘/nix/store/20h8cva19irq8vn39i72j8iz40ivijhr-myShell.drv’ failed with exit code 1
error: build of ‘/nix/store/20h8cva19irq8vn39i72j8iz40ivijhr-myShell.drv’ failed

答案 1 :(得分:0)

为了使这段代码更加惯用,我有以下建议:

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。根据我的经验,尼克斯有一个非常热情的社区。