如何使用“nix-shell”固定软件包版本?

如何使用“nix-shell”固定软件包版本?

据我了解,我可以使用该标志来使用给定版本的 Nix 软件包-I。但我想知道在一个shell.nixconf中是否可以有类似的东西:

  • gitv2.1.2
  • htopv1.2.3
  • ...

能够确保给定的工具版本。

答案1

是的,有多种方法可以做到这一点,但没有一种方法像这样直接和简单,git v2.1.2; htop v1.2.3并且有很多注意事项。

在旁边
指定编程语言包的版本也是可能的,但这个主题似乎更混乱。迄今为止最有前途的标准化工作是dream2nix

0. 方法

也就是说,在撰写本文时可用:

0.1“版本化”属性路径(如果可用)

单版本政策

仅当有充分理由时,我们才会在 nixpkgs 中保留多个版本。 Nix 能够处理任意数量的版本/配置,但另一方面,当所有(或大多数)仅使用一个版本/配置时,它会更方便。它可以在许多方面更好地共享工作:简化维护、测试、共享二进制文件等。这是大多数发行版所做的。 (只有 gentoo 与我所知道的那些大的有所不同,并且他们为此付出了代价。)

当我们创建更多变体时,我们只需命名它们(属性路径),例如gcc48andgcc49ffmpegand ffmpeg-full

--vcunat 于 2015 年 9 月 6 日发表评论Nixpkgs 问题 #9682

引用jtojnar 的话语回答更具体的例子:

$ nix-env -qP --available nodejs
nixos.nodejs       nodejs-10.18.1
nixos.nodejs-10_x  nodejs-10.18.1
nixos.nodejs-12_x  nodejs-12.14.1
nixos.nodejs-13_x  nodejs-13.6.0
$ nix-env -iA nixos.nodejs-13_x

0.2固定

显式或隐式地与

  • Nix 推导表达式(参见示例 2.2)
  • Nix 命令行工具(参见示例 2.1)
  • 覆盖层
  • 覆盖(参见示例 2.3)
  • 薄片(默认为固定)
  • 第三方、“非官方”和/或专有方法(例如,niv,niv+ 家庭管家,弗洛克斯

1. 条款

1.1 固定

我能找到的最好的描述是这条评论由CMCD龙凯;解释一下:

固定在一个尼克斯表达意味着使用一个尼克斯套装(通常尼克斯包装或其分叉)在其历史的特定点(即某种状态)。

使用 Git (内容寻址)提交哈希值尼克斯包装repo 类似于“分离头状态”:从 Nix 表达式的角度来看,每个包定义都是发布提交时的最新版本。

例如,当引用固定到的 Nixpkgs 软件包集时39cd40f(2017 年 9 月 29 日),“最新”版本为:

警告
Nixpkgs 存储库跟踪官方 Nix 软件包集Nix 表达式中使用的便捷工具!请参阅下面的示例 2.1,了解这如何打破假设。

据我所知,任何官方文档中仍然没有定义术语“固定”。 (这Nixpkgs 手册曾经用一个例子提到过它,但没有解释。)

1.2 Nix表达

使用以下代码编写的一段代码Nix 表达语言

1.3 Nix推导表达式

A尼克斯表达这将评估为尼克斯推导(通常通过最终调用derivation(来源普里莫普,最常见的是通过mkShell来源) 或者mkDerivation来源))。

笔记:Nix 推导与 Nix 推导表达式

当我明确区分 Nix 和 Nix 时,我更容易对 Nix 进行推理。尼克斯推导以及计算结果为尼克斯推导(即,Nix 推导表达式)。是否尝试使其更清楚这个答案,但它需要更新,所以要持保留态度。

1.4 普里莫普

原始操作,或普里莫普斯,是语言中内置的函数。它们不需要定义或导入;默认情况下它们在范围内。但由于它们是正常的标识符,因此它们被本地定义覆盖。

--Eelco Dolstra,纯功能软件部署模型(博士论文)(2006 年 1 月 18 日)

这些实施于NixOS/nix回购。

1.5 Nix推导

(占位符

1.6 套餐设置

什么是套装?关于 NixOS 的讨论,但是解释一下ryantm 的回答:

套餐套装是一个集合尼克斯表达s 评估为属性集(也称为“attrset”)其中名称是包的名称(或递归的名称)套装) 的值是尼克斯推导

例子:

2. 示例

2.1 将 Nixpkg 固定在nix-shell调用上

压缩常用的 Nix-shell 表达式,

{ pkgs ? import <nixpkgs> {} }:

pkgs.mkShell {

  buildInputs = [
    pkgs.git
    pkgs.htop
  ];

  shellHook = ''
    echo "git:  $(git  --version)"
    echo "htop: $(htop --version)"
  '';
}

变成单行,然后

nix-shell \
-I nixpkgs=https://github.com/NixOS/nixpkgs/archive/39cd40f7bea40116ecb756d46a687bfd0d2e550e.tar.gz \
-E '{ pkgs ? import <nixpkgs> {} }: pkgs.mkShell { buildInputs = [ pkgs.git pkgs.htop ]; shellHook = "echo \"git: $(git --version)\"; echo \"htop: $(htop --version)\";"; }'

不会工作,因为mkShell尚未实施,因此:

nix-shell \
-I nixpkgs=https://github.com/NixOS/nixpkgs/archive/39cd40f7bea40116ecb756d46a687bfd0d2e550e.tar.gz \
-E '{ pkgs ? import <nixpkgs> {} }: pkgs.stdenv.mkDerivation { name = "shell"; buildInputs = [ pkgs.git pkgs.htop ]; shellHook = "echo \"git: $(git --version)\"; echo \"htop: $(htop --version)\";"; }'

笔记:

  • 两个片段之间的唯一区别是该部分pkgs.mkShell { buildInputs已替换为pkgs.stdenv.mkDerivation { name = "shell"; buildInputs.

  • 在 Ubuntu 22.04 上运行这两个命令 ( aarch64);另外,第二个不会在 上运行aarch64-darwin

2.2 在 Nix 表达式中固定 Nixpkg

使用杰夫·海金的评论作为模板:

步骤 0. 找到您想要的版本

使用查找(几乎)包的所有版本lazamar 绝对令人惊叹的在线工具

第 1 步:使用哈希值安装该版本

单击您需要的版本所在行中的哈希值(例如,git2.23.0htop2.2.0),然后一一使用列出的nix-env/命令,或者将 Nix 表达式片段复制到文件中(并重命名为变量以避免冲突):nix-shell


# git_htop.nixshell

let

  pkgs_for_git = import (builtins.fetchTarball {
    url = "https://github.com/NixOS/nixpkgs/archive/bca9437d1eae9519b61a58f2593f25f65494f8e9.tar.gz";
  }) {};

  pkgs_for_htop = import (builtins.fetchTarball {
    url = "https://github.com/NixOS/nixpkgs/archive/b5e903cedb331f9ee268ceebffb58069f1dae9fb.tar.gz";
  }) {};

  # Copied lines above from lazamar's tool,
  # but the shortened form works too:
  #
  #   pkgs = import (builtins.fetchTarball "<url>") {};

in
  
  # Chose `pkgs_for_htop` arbitrarily; what matters
  # is that the  derivation function  exists in the
  # pinned Nixpkgs.

  pkgs_for_htop.mkShell {

    buildInputs = [
      pkgs_for_htop.htop
      pkgs_for_git.git
    ];

    shellHook = ''
      echo "git:  $(git  --version)"
      echo "htop: $(htop --version)"
    '';
  }

然后调用它:

nix-shell -v git_htop.nixshell

2.3 指定带有覆盖层的包(存根)

简单链接nix-config来自 jwiegley仓库的文件;虽然我还不明白,但还是想把它包括进去。

3. 进一步阅读

围绕这个仍在发展的话题的在线讨论:


(希望通过更多示例来扩展这一点。)

答案2

您可以导入包含特定软件包版本的散列的 nixpkgs 存档。例如,您可以找到哈希值这里

{ pkgs ? import <nixpkgs> { } }:

let
  gitPkgsHash = "0c159930e7534aa803d5cf03b27d5c86ad6050b7"; #git 2.16.2
  htopPkgsHash = "5ed9176c52e4ceed2755a19b3e8357a0772de8ff"; #htop 2.0.0
  gitPkgs = import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/${gitPkgsHash}.tar.gz") { };
  htopPkgs = import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/${htopPkgsHash}.tar.gz") { };
in

pkgs.mkShell {
  buildInputs = [
    gitPkgs.gitAndTools.gitFull
    htopPkgs.htop
  ];
}

附言。在此配置中,我使用了较新的版本,因为您的版本非常旧并导致了一些错误

相关内容