如何强制 Nix 通过在本地构建软件包来“安装软件包”,而不是下载预先构建的二进制文件?

tor*_*tte 3 nixos nix

通过“安装包”,我的意思是评估 Nix 构建表达式(使用nix-envnix-shell -p等)从源代​​码构建,而不是使用替代品

最初发布在 Stackoverflow 上,但 [Charles Duffy 指出][3] 如果它是关于命令行工具或配置的,那么在这里更合适。仍然把它留在那里,因为我假设通过使用 Nix 语言本身可以强制包始终从源代码编译,我只是还不知道如何做。(或者如果实际上不可能,有人会指出,那么这个问题就属于这里。)

tor*_*tte 9

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

\n
nix-env --options substitute false -i hello\n\nnix-shell --options substitute false -p hello\n
Run Code Online (Sandbox Code Playgroud)\n
\n

可能不是您要找的机器人

\n

正如 Robert Hensing(评论聊天)、Henri Menke(评论)和 Vladim\xc3\xadr \xc4\x8cun\xc3\xa1t(评论)指出的那样,这可能不是您真正想要的东西。

\n

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

\n

试图用最简单的方法来解决这个问题,即获取我的分叉并使用新源重新构建它,所以我将其归结为这个问题。尽管如此,我怀疑对我来说正确的方向是NixOS Wiki中的Nixpkgs/Create and debug packages

\n

仅重新构建包本身

\n

Vladim\xc3\xadr \xc4\x8cun\xc3\xa1t 评论道:“禁用替代项会让您重建本地缺少的所有内容,尽管我怀疑提出此类问题的人通常只想重建指定的包本身。

\n

(这可能是通过nix-build或“只是”覆盖原始包来实现的,但可能是错误的。后者在 NixOS wiki 文章开发环境nix-shell中提到(甚至可能被演示?) ,但尚未能够彻底阅读它。 )

\n

测试再现性

\n

如果人们想确保后续构建是确定性的,那么他们可能会提出同样的问题。正如亨利·门克(Henri Menke)评论的那样,人们应该使用nix-build --check它。

\n

这个--check选项很容易被错过;它没有记录man nix-buildNix 手册nix-build中,而是记录在因为(如所解释的那样):nix-store --realizeman nix-build

\n
\n

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

\n
\n

请参阅Nix 手册第18.1 节中的详细示例。抽查构建确定性及其之后的下一部分

\n
\n

Nix 手册部分substitute配置选项相关部分nix.conf

\n
\n

姓名

\n

nix.conf\xe2\x80\x94 Nix 配置文件

\n

描述

\n

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

\n
    \n
  • 系统范围的配置文件sysconfdir/nix/nix.conf(即/etc/nix/nix.conf在大多数系统上),或者$NIX_CONF_DIR/nix.conf如果NIX_CONF_DIR已设置。

    \n
  • \n
  • 用户配置文件$XDG_CONFIG_HOME/nix/nix.conf,或者~/.config/nix/nix.conf如果XDG_CONFIG_HOME没有设置。

    \n
  • \n
\n

--option您可以使用标志覆盖命令行上的设置,\ne.g。--option keep-outputs false

\n

目前可以使用以下设置:

\n

[..]

\n

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

\n
\n

(原名use-binary-caches。)

\n
\n \n注释\n

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

\n

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

\n

因此,如果有人要对一个包进行一些轻微的黑客攻击,并且只想在本地尝试一下(例如,使用nix-shell),那么就必须使用-I nixpkgs=a/local/nixpkgs/dir来获取这些更改 - 并最终进行重新编译?或者应该使用吗nix-build

\n

另请参阅问题如何nix-build再次构建存储路径?\n

\n

  • 请注意,禁用替代品会使您重建本地缺少的“所有内容”,尽管我怀疑提出此类问题的人通常只想重建指定的包本身。 (2认同)