如何通过在本地构建而不是下载预构建的二进制文件来强制 Nix“安装包”? 仅重新构建包本身再现性测试姓名说明

问题描述

安装包”是指评估 Nix 构建表达式(使用 nix-envnix-shell -p 等)从源代​​码构建而不是使用 {{3 }}。

还有substitute,因为和cross-posted to Unix& Linux一样,如果它是关于命令行工具或配置的,那么它更多是关于主题的。仍然留在这里是因为我认为只使用 Nix 语言就可以强制一个包总是从源代码编译,我只是不知道如何。 (或者如果实际上不可能,有人会指出,那么这个问题确实属于这里。)

解决方法

substitute option 中将 nix.conf 设置为 false(默认为 true)或在调用 Nix 命令时使用 --option substitute false

nix-env --options substitute false -i hello

nix-shell --options substitute false -p hello

可能不是您要找的机器人

正如 Robert Hensing (comment,chat)、Henri Menke (comment) 和 Vladimír Čunát (comment) 指出的那样,这可能不是你真的很在乎。

详细说明:我一直自信地使用最基本的 Nix 功能,但到了需要维护和部署用 C 编写的大型应用程序的自定义分支的地步,这在开始时非常令人生畏。

>

试图以最简单的方式解决问题,只需 fetch 我的叉子并使用新源重新构建它,所以我将其归结为这个问题。虽然,我怀疑对我来说正确的方向是沿着 Nixpkgs/Create and debug packages 中的 NixOS Wiki 的路线。

仅重新构建包本身

Vladimír Čunát commented禁用替代品会让你重建本地缺少的所有东西,尽管我怀疑问这样问题的人通常只想重建指定的包本身。” >

(这可能是通过 nix-build 或“只是”覆盖原始包实现的,但可能是错误的。后者在 NixOS wiki 文章 Development environment with nix-shell 中被提及(甚至可能被证明?)但没有还没能彻底读完。)

再现性测试

如果他们想确保后续构建是确定性的,那么他们可能会提出同样的问题。作为 Henri Menke comments,应该使用 nix-build --check

--check 选项很容易错过;它没有记录在 man nix-buildnix-buildNix manual 中,而是记录在 nix-store --realize 中,因为(如 man nix-build 解释的那样):

nix-build 本质上是 nix-instantiate 的包装器(为了 将高级 Nix 表达式转换为低级存储派生) 和 nix-store --realise(构建商店派生)[等等] 所有 此处未列出的选项将传递给 nix-store --realise,除了 用于传递给 --arg--attr-A / nix-instantiate

请参阅 Nix manual18.1. Spot-Checking Build Determinism 处的 the next section right after it 中的详细示例。


the nix.conf sectionNix manual 下的 substitute 配置选项的相关部分:

姓名

nix.conf — Nix 配置文件

说明

Nix 从两个配置文件中读取设置:

  • 系统范围的配置文件 sysconfdir/nix/nix.conf(即在大多数系统上为 /etc/nix/nix.conf),如果设置了 $NIX_CONF_DIR/nix.conf,则为 NIX_CONF_DIR

  • 用户配置文件 $XDG_CONFIG_HOME/nix/nix.conf,如果 ~/.config/nix/nix.conf 未设置,则为 XDG_CONFIG_HOME

您可以使用 --option 标志覆盖命令行上的设置, 例如--option keep-outputs false

以下设置当前可用:

[..]

替代
如果设置为 true(默认),Nix 将使用二进制替代品(如果可用)。可以禁用此选项以强制从源代码构建。

(以前称为 use-binary-caches。)


注意事项

如果命令多次发出,将 substitute 设置为 false(使用 --options 或在 nix.conf 中)不会重新编译程序包。也就是说,上面的 hello 会第一次从源代码编译,如果再次发出命令,它将访问已经存在的存储路径。

这就是它变得模糊的地方:很明显没有重新编译发生,因为除非包的 Nix 构建表达式没有改变,否则存储输出哈希也不会改变,使得下一个编译输出等同于前一个,因此该操作将是多余的。

因此,如果您想对软件包进行一些轻微的修改,并且只想在本地试用(例如,使用 nix-shell),那么您将不得不使用 -I nixpkgs=a/local/nixpkgs/dir 来获取这些更改 -并最终重新编译?还是应该使用nix-build

另见问题 How to nix-build again a built store path?