nix-direnv
direnv 中 use_nix 和 use_flake 的更快、持久化实现,
用于替换内置版本。
主要特性:
- 通过缓存
nix-shell环境,在首次运行后显著提速 - 通过在用户的
gcroots中符号链接生成的 shell 派生,防止构建依赖项被垃圾回收(人生苦短, 在飞机上没有网络连接时,不应丢失项目的构建缓存)
为什么不使用 lorri?
与 lorri 相比,nix-direnv 更简单(且无需外部守护进程)。此外,lorri 有时 会在每次更改时重新评估整个 nixpkgs(导致 CPU 负载持续偏高)。
安装
要求:
- bash 4.4
- nix 2.4 或更高版本
- direnv 2.21.3 或更高版本
[!WARNING]
我们假设 direnv 已正确安装,因为 nix-direnv 并非常规 direnv 的替代品 (仅替代其 部分功能)。
[!NOTE]
nix-direnv 需要现代版本的 Bash。MacOS 自带 2007 年的 bash 3.2。作为 变通方案,我们建议 macOS 用户通过 Nix 或 Homebrew 安装direnv。 安装 nix-direnv 有多种方式,请选择您喜欢的方式:
通过 home-manager(推荐)
通过 home-manager
请注意,虽然推荐使用 home-manager 集成,但某些用例需要仅存在于某些 nix-direnv 版本中的功能。使用此方法更难控制所安装的 nix-direnv 的版本。如果您需要如此具体的控制,请使用其他方法安装 nix-direnv。
在 $HOME/.config/home-manager/home.nix 中添加
{
# ...other config, other config...
programs = {
direnv = {
enable = true;
enableBashIntegration = true; # see note on other shells below
nix-direnv.enable = true;
};
bash.enable = true; # see note on other shells below
};
}
检查当前
Home Manager 选项
以集成除 Bash 以外的 shell。请务必同时允许
home-manager 使用 programs.<your_shell>.enable = true 管理你的 shell。
Direnv 的 source_url
Direnv source_url
将以下行放入你的 .envrc:
if ! has nix_direnv_version || ! nix_direnv_version 3.2.0; then
source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.2.0/direnvrc" "sha256-hW6NC1JHue3IjZN3uDM6l6I2PMaauqd2D7hXYJ1Zfr4="
fi
通过 NixOS 系统配置
通过 NixOS 系统配置
对于 NixOS 23.05+,所需的全部是
{
programs.direnv.enable = true;
}
其他可用选项为:
{ pkgs, ... }: {
#set to default values
programs.direnv = {
package = pkgs.direnv;
silent = false;
loadInNixShell = true;
direnvrcExtra = "";
nix-direnv = {
enable = true;
package = pkgs.nix-direnv;
};
}
使用 `nix profile`
使用 nix profile
以非 root 用户身份执行以下操作:
nix profile install nixpkgs#nix-direnv
然后将 nix-direnv 添加到 $HOME/.config/direnv/direnvrc:
source $HOME/.nix-profile/share/nix-direnv/direnvrc
From source
From source
将仓库克隆到某个目录,然后在你的 ~/.config/direnv/direnvrc 中 source 该仓库中的 direnvrc:
# put this in ~/.config/direnv/direnvrc
source $HOME/nix-direnv/direnvrc
使用示例
在项目中添加 shell.nix 或一个 default.nix 到项目目录:
# save this as shell.nix
{ pkgs ? import <nixpkgs> {}}:
pkgs.mkShell {
packages = [ pkgs.hello ];
}
然后在你的 envrc 中添加行 use nix:
echo "use nix" >> .envrc
direnv allow
如果你之前没有使用过 direnv,请确保 先将其集成到你的 shell 中。
使用非标准文件名
你可以通过在 .envrc 中传递文件名,使用不同于 shell.nix 或 default.nix 的文件名,例如:
echo "use nix foo.nix" >> .envrc
Flakes 支持
nix-direnv 还附带一个替代的 use_flake 实现。该代码
已进行测试且可以正常工作,但上游 flake api 尚未最终确定,因此我们
无法保证在 nix 升级后的稳定性。
与 use_nix 类似,我们的 use_flake 将阻止已下载
软件包的垃圾回收,包括 flake 输入。
创建新的 flake 原生项目
本仓库附带一个
flake 模板.
它提供了一个带有 devShell 集成和基本 .envrc 的基础 flake。
要使用此模板,您可以执行以下命令:
nix flake new -t github:nix-community/nix-direnv <desired output path>
与现有 flake 集成
echo "use flake" >> .envrc && direnv allow
第 use flake 行还接受一个额外的任意 flake 参数,因此
你可以按如下方式指向外部 flakes:
use flake ~/myflakes#project
高级用法
使用 flake
在底层,use_flake 调用了 nix print-dev-env。use_flake 函数的第一个参数是要使用的 flake 表达式,所有其他参数
都会代理传递给对 print-dev-env 的调用。你可以利用这一事实
进行一些更复杂的调用。
例如,如果你有一个在某些条件下需要以非纯方式调用的 flake,你可能希望向 print-dev-env 调用传递 --impure,
以便传入调用 shell 的环境。
你可以按以下方式操作:
echo "use flake . --impure" > .envrc
direnv allow
使用 nix
与 use flake 类似,use nix 现在使用 nix print-dev-env。由于历史
原因,参数解析模拟了 nix shell。
这导致我们在合理解析方面存在一些限制。
目前,所有单词参数以及一些已知的双词参数将 被解释或传递。
细粒度行为控制
禁用 devShell 回退
默认情况下,如果 nix-direnv 发现
新版本无法求值,它将重新加载之前可用的 devShell。可以通过在 .envrc 中调用
nix_direnv_disallow_fallback 来禁用此行为,如下所示:
nix_direnv_disallow_fallback
use nix # or use flake
手动重新加载 nix 环境
为了避免在意外时间出现延迟和耗时的重建,你可以使用 nix-direnv 的“手动重新加载”模式。此时 nix-direnv 会告知你 nix 环境已不再最新。你可以自行决定何时 重新加载 nix 环境。
要启用手动模式,请在你的 .envrc 中使用 nix_direnv_manual_reload,
如下所示:
nix_direnv_manual_reload
use nix # or use flake
要重新加载你的 nix 环境,请使用 nix-direnv-reload 命令:
nix-direnv-reload
已知参数
-p: 开始一个要安装的包列表;消耗所有剩余参数--include/-I: 将以下路径添加到<...>文件名的查找位置列表中--attr/-A: 指定要使用的输出属性
--command、--run、--exclude、--pure、-i 和 --keep 被显式
忽略。
所有单词参数(-j4、--impure 等)都会传递给底层的
nix 调用。
跟踪的文件
作为便利功能,nix-direnv 会自动将常见文件添加到 direnv 的监视文件列表中。
额外跟踪的文件列表如下:
-
对于
use nix:~/.direnvrc~/.config/direnv/direnvrc.envrc,- 单个 nix 文件。按优先级顺序:
use nix的文件参数- 如果存在
default.nix - 如果存在
shell.nix
-
对于
use flake:~/.direnvrc~/.config/direnv/direnvrc.envrcflake.nixflake.lock- 如果存在
devshell.toml
用户可以自由使用 direnv 的内置 watch_file 函数来跟踪额外的
文件。watch_file 必须在调用 use flake 或 use nix 之前
调用才能生效。
环境变量
nix-direnv 设置以下环境变量供用户使用。所有 其他环境变量要么是底层 nix 调用的产物,要么纯属偶然,不应依赖。
NIX_DIRENV_DID_FALLBACK: 当当前 nix shell 或 flake 的 devShell 修订版本无效,且 nix-direnv 已加载最后已知可用的 shell 时设置。
nix-direnv 还尊重以下环境变量用于配置。
NIX_DIRENV_FALLBACK_NIX: 可设置为备用 Nix 二进制文件位置,当PATH中没有兼容版本时使用。如果通过 NixOS 模块安装,默认值为config.nix.package,否则需要手动设置。如果未设置或为空,当在PATH上找不到 Nix 实现时将立即失败。
General direnv tips
- 更改 direnv 缓存存储位置
- 在新 nix 项目中快速设置 direnv
- 禁用 diff 通知(需要 direnv 2.34+): 注意, 这属于 direnv 的 TOML 配置!
Recommended integration
- direnv-instant - 一个非阻塞 守护进程,通过异步在后台运行 direnv 使其真正即时。与 nix-direnv 的缓存结合使用时, 它提供即时的 shell 访问,同时环境加载在后台进行, 并在环境就绪时自动通知。
Other projects in the field
Need commercial support or customization?
如需商业支持,请联系 Mic92 joerg@thalheim.io 或联系 Numtide。