mirror of
https://github.com/ryan4yin/nixos-and-flakes-book.git
synced 2024-11-21 23:53:12 +01:00
feat: update contents about lib.mkBefore & lib.mkAfter
This commit is contained in:
parent
883393eeb9
commit
50ef281137
@ -185,6 +185,8 @@ Then, for my desktop machine, I override the value in [ryan4yin/nix-config/blob/
|
||||
|
||||
In addition to `lib.mkDefault` and `lib.mkForce`, there are also `lib.mkBefore` and `lib.mkAfter`, which are used to set the merge order of **list-type options**. These functions further contribute to the modularization of the configuration.
|
||||
|
||||
> I haven't found the official documentation for list-type options, but I simply understand that they are types whose merge results are related to the order of merging. According to this understanding, both `list` and `string` types are list-type options, and these functions can indeed be used on these two types in practice.
|
||||
|
||||
As mentioned earlier, when you define multiple values with the same **override priority**, Nix will throw an error. However, by using `lib.mkOrder`, `lib.mkBefore`, or `lib.mkAfter`, you can define multiple values with the same override priority, and they will be merged in the order you specify.
|
||||
|
||||
To examine the source code of `lib.mkBefore`, you can run `nix repl -f '<nixpkgs>'` and then enter `:e lib.mkBefore`. To learn more about `nix repl`, type `:?` for the help information:
|
||||
@ -210,69 +212,86 @@ Therefore, `lib.mkBefore` is a shorthand for `lib.mkOrder 500`, and `lib.mkAfter
|
||||
|
||||
To test the usage of `lib.mkBefore` and `lib.mkAfter`, let's create a simple Flake project:
|
||||
|
||||
```shell{16-29}
|
||||
# Create flake.nix with the following content
|
||||
› cat <<EOF | sudo tee flake.nix
|
||||
```nix{10-38}
|
||||
# flake.nix
|
||||
{
|
||||
description = "Ryan's NixOS Flake";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, ... }@inputs: {
|
||||
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
|
||||
outputs = {nixpkgs, ...}: {
|
||||
nixosConfigurations = {
|
||||
"nixos-test" = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
|
||||
modules = [
|
||||
# Demo module 1: insert 'git' at the head of the list
|
||||
({lib, pkgs, ...}: {
|
||||
environment.systemPackages = lib.mkBefore [pkgs.git];
|
||||
({lib, ...}: {
|
||||
programs.bash.shellInit = lib.mkBefore ''
|
||||
echo 'insert before default'
|
||||
'';
|
||||
programs.zsh.shellInit = lib.mkBefore "echo 'insert before default';";
|
||||
nix.settings.substituters = lib.mkBefore [
|
||||
"https://nix-community.cachix.org"
|
||||
];
|
||||
})
|
||||
|
||||
# Demo module 2: insert 'vim' at the tail of the list
|
||||
({lib, pkgs, ...}: {
|
||||
environment.systemPackages = lib.mkAfter [pkgs.vim];
|
||||
({lib, ...}: {
|
||||
programs.bash.shellInit = lib.mkAfter ''
|
||||
echo 'insert after default'
|
||||
'';
|
||||
programs.zsh.shellInit = lib.mkAfter "echo 'insert after default';";
|
||||
nix.settings.substituters = lib.mkAfter [
|
||||
"https://ryan4yin.cachix.org"
|
||||
];
|
||||
})
|
||||
|
||||
# Demo module 3: simply add 'curl' to the list
|
||||
({lib, pkgs, ...}: {
|
||||
environment.systemPackages = with pkgs; [curl];
|
||||
({lib, ...}: {
|
||||
programs.bash.shellInit = ''
|
||||
echo 'this is default'
|
||||
'';
|
||||
programs.zsh.shellInit = "echo 'this is default';";
|
||||
nix.settings.substituters = [
|
||||
"https://nix-community.cachix.org"
|
||||
];
|
||||
})
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
EOF
|
||||
|
||||
# Create flake.lock
|
||||
› nix flake update
|
||||
|
||||
# Enter the nix repl environment
|
||||
› nix repl
|
||||
Welcome to Nix 2.13.3. Type :? for help.
|
||||
|
||||
# Load the flake we just created
|
||||
nix-repl> :lf .
|
||||
Added 9 variables.
|
||||
|
||||
# Check the order of systemPackages
|
||||
nix-repl> outputs.nixosConfigurations.nixos-test.config.environment.systemPackages
|
||||
[ «derivation /nix/store/0xvn7ssrwa0ax646gl4hwn8cpi05zl9j-git-2.40.1.drv»
|
||||
«derivation /nix/store/7x8qmbvfai68sf73zq9szs5q78mc0kny-curl-8.1.1.drv»
|
||||
«derivation /nix/store/bly81l03kh0dfly9ix2ysps6kyn1hrjl-nixos-container.drv»
|
||||
......
|
||||
......
|
||||
«derivation /nix/store/qpmpv
|
||||
|
||||
q5azka70lvamsca4g4sf55j8994-vim-9.0.1441.drv» ]
|
||||
```
|
||||
|
||||
As you can see, the order of `systemPackages` is `git -> curl -> default packages -> vim`, which matches the order we defined in `flake.nix`.
|
||||
The flake above contains the usage of `lib.mkBefore` and `lib.mkAfter` on multiline strings, single-line strings, and lists. Let's test the results:
|
||||
|
||||
```bash
|
||||
# Example 1: multiline string merging
|
||||
› echo $(nix eval .#nixosConfigurations.nixos-test.config.programs.bash.shellInit)
|
||||
trace: warning: system.stateVersion is not set, defaulting to 23.11. Read why this matters on https://nixos.org/manual/nixos/stable/options.html#opt-system.stateVersio
|
||||
n.
|
||||
"echo 'insert before default'
|
||||
|
||||
echo 'this is default'
|
||||
|
||||
if [ -z \"$__NIXOS_SET_ENVIRONMENT_DONE\" ]; then
|
||||
. /nix/store/60882lm9znqdmbssxqsd5bgnb7gybaf2-set-environment
|
||||
fi
|
||||
|
||||
|
||||
|
||||
echo 'insert after default'
|
||||
"
|
||||
|
||||
# example 2: single-line string merging
|
||||
› echo $(nix eval .#nixosConfigurations.nixos-test.config.programs.zsh.shellInit)
|
||||
"echo 'insert before default';
|
||||
echo 'this is default';
|
||||
echo 'insert after default';"
|
||||
|
||||
# Example 3: list merging
|
||||
› nix eval .#nixosConfigurations.nixos-test.config.nix.settings.substituters
|
||||
[ "https://nix-community.cachix.org" "https://nix-community.cachix.org" "https://cache.nixos.org/" "https://ryan4yin.cachix.org" ]
|
||||
|
||||
```
|
||||
|
||||
As you can see, `lib.mkBefore` and `lib.mkAfter` can define the order of merging of multiline strings, single-line strings, and lists. The order of merging is the same as the order of definition.
|
||||
|
||||
> Although adjusting the order of `systemPackages` may not be useful in practice, it can be helpful in other scenarios.
|
||||
|
||||
> For a deeper introduction to the module system, see [Module System & Custom Options](../other-usage-of-flakes/module-system.md).
|
||||
|
||||
|
@ -162,6 +162,8 @@ Nix Flakes 对目录结构没有任何要求,你可以参考上面的例子,
|
||||
|
||||
`lib.mkBefore` 跟 `lib.mkAfter` 用于设置**列表类型**的合并顺序,它们跟 `lib.mkDefault` 和 `lib.mkForce` 一样,也被用于模块化配置。
|
||||
|
||||
> 列表类型的定义我没找到官方文档,但我简单理解,应该就是合并结果与合并先后顺序有关的类型。按这个理解,list 跟 string 类型都是列表类型,实际测试这几个函数也确实能用在这两个类型上。
|
||||
|
||||
前面说了如果你定义了多个优先级相同的值,Nix 会报错说存在参数冲突,需要你手动解决。
|
||||
|
||||
但是如果你定义的是**列表类型**的值,Nix 就不会报错了,因为 Nix 会把你定义的多个值合并成一个列表,而 `lib.mkBefore` 跟 `lib.mkAfter` 就是用于设置这个列表的合并顺序的。
|
||||
@ -189,67 +191,86 @@ Nix Flakes 对目录结构没有任何要求,你可以参考上面的例子,
|
||||
|
||||
为了更直观地理解这两个函数,现在来创建一个 flake 测试下:
|
||||
|
||||
```shell{16-29}
|
||||
# 使用如下内容创建一个 flake.nix 文件
|
||||
› cat <<EOF | sudo tee flake.nix
|
||||
```nix{10-38}
|
||||
# flake.nix
|
||||
{
|
||||
description = "Ryan's NixOS Flake";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, ... }@inputs: {
|
||||
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
|
||||
outputs = {nixpkgs, ...}: {
|
||||
nixosConfigurations = {
|
||||
"nixos-test" = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
|
||||
modules = [
|
||||
# demo module 1, 在列表头插入 git
|
||||
({lib, pkgs, ...}: {
|
||||
environment.systemPackages = lib.mkBefore [pkgs.git];
|
||||
({lib, ...}: {
|
||||
programs.bash.shellInit = lib.mkBefore ''
|
||||
echo 'insert before default'
|
||||
'';
|
||||
programs.zsh.shellInit = lib.mkBefore "echo 'insert before default';";
|
||||
nix.settings.substituters = lib.mkBefore [
|
||||
"https://nix-community.cachix.org"
|
||||
];
|
||||
})
|
||||
|
||||
# demo module 2, 在列表尾插入 vim
|
||||
({lib, pkgs, ...}: {
|
||||
environment.systemPackages = lib.mkAfter [pkgs.vim];
|
||||
({lib, ...}: {
|
||||
programs.bash.shellInit = lib.mkAfter ''
|
||||
echo 'insert after default'
|
||||
'';
|
||||
programs.zsh.shellInit = lib.mkAfter "echo 'insert after default';";
|
||||
nix.settings.substituters = lib.mkAfter [
|
||||
"https://ryan4yin.cachix.org"
|
||||
];
|
||||
})
|
||||
|
||||
# demo module 3, 添加 curl,但是不设置优先级
|
||||
({lib, pkgs, ...}: {
|
||||
environment.systemPackages = with pkgs; [curl];
|
||||
({lib, ...}: {
|
||||
programs.bash.shellInit = ''
|
||||
echo 'this is default'
|
||||
'';
|
||||
programs.zsh.shellInit = "echo 'this is default';";
|
||||
nix.settings.substituters = [
|
||||
"https://nix-community.cachix.org"
|
||||
];
|
||||
})
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
EOF
|
||||
|
||||
# 生成 flake.lock
|
||||
› nix flake update
|
||||
|
||||
# 进入 nix REPL 解释器
|
||||
› nix repl
|
||||
Welcome to Nix 2.13.3. Type :? for help.
|
||||
|
||||
# 将我们刚刚创建好的 flake 加载到当前作用域中
|
||||
nix-repl> :lf .
|
||||
Added 9 variables.
|
||||
|
||||
# 检查下 systemPackages 的顺序,看看跟我们预期的是否一致
|
||||
nix-repl> outputs.nixosConfigurations.nixos-test.config.environment.systemPackages
|
||||
[ «derivation /nix/store/0xvn7ssrwa0ax646gl4hwn8cpi05zl9j-git-2.40.1.drv»
|
||||
«derivation /nix/store/7x8qmbvfai68sf73zq9szs5q78mc0kny-curl-8.1.1.drv»
|
||||
«derivation /nix/store/bly81l03kh0dfly9ix2ysps6kyn1hrjl-nixos-container.drv»
|
||||
......
|
||||
......
|
||||
«derivation /nix/store/qpmpvq5azka70lvamsca4g4sf55j8994-vim-9.0.1441.drv» ]
|
||||
```
|
||||
|
||||
能看到 `systemPackages` 的顺序是 `git -> curl -> default packages -> vim`,跟我们预期的一致。`lib.mkBefore [pkgs.git]` 确实是将 `git` 插入到了列表头,而 `lib.mkAfter [pkgs.vim]` 则是将 `vim` 插入到了列表尾。
|
||||
上面的例子包含了在多行字符串、单行字符串,以及列表三种类型上应用 `lib.mkBefore` 和 `lib.mkAfter`,下面测试下结果:
|
||||
|
||||
```bash
|
||||
# 示例一:多行字符串合并
|
||||
› echo $(nix eval .#nixosConfigurations.nixos-test.config.programs.bash.shellInit)
|
||||
trace: warning: system.stateVersion is not set, defaulting to 23.11. Read why this matters on https://nixos.org/manual/nixos/stable/options.html#opt-system.stateVersio
|
||||
n.
|
||||
"echo 'insert before default'
|
||||
|
||||
echo 'this is default'
|
||||
|
||||
if [ -z \"$__NIXOS_SET_ENVIRONMENT_DONE\" ]; then
|
||||
. /nix/store/60882lm9znqdmbssxqsd5bgnb7gybaf2-set-environment
|
||||
fi
|
||||
|
||||
|
||||
|
||||
echo 'insert after default'
|
||||
"
|
||||
|
||||
# 示例二:单行字符串合并
|
||||
› echo $(nix eval .#nixosConfigurations.nixos-test.config.programs.zsh.shellInit)
|
||||
"echo 'insert before default';
|
||||
echo 'this is default';
|
||||
echo 'insert after default';"
|
||||
|
||||
# 示例三:列表合并
|
||||
› nix eval .#nixosConfigurations.nixos-test.config.nix.settings.substituters
|
||||
[ "https://nix-community.cachix.org" "https://nix-community.cachix.org" "https://cache.nixos.org/" "https://ryan4yin.cachix.org" ]
|
||||
|
||||
```
|
||||
|
||||
可以看到,`lib.mkBefore` 会将后面的值插入到前面,而 `lib.mkAfter` 会将后面的值插入到前面。
|
||||
|
||||
> 虽然单纯调整 `systemPackages` 的顺序没什么用,但是在其他地方可能会有用...
|
||||
|
||||
> 对模块系统更深入的介绍,参见 [模块系统与自定义 options](../other-usage-of-flakes/module-system.md).
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user