nixos-and-flakes-book/docs/nixpkgs/callpackage.md

69 lines
3.3 KiB
Markdown
Raw Normal View History

## pkgs.callPackage
2023-06-24 04:24:00 +00:00
In the previous content, We have used `import xxx.nix` to import Nix files many times, this syntax simply returns the execution result of the file, without any further processing of it.
`pkgs.callPackage` is also used to import Nix files, its syntax is `pkgs.callPackage xxx.nix { ... }`, but unlike `import`, the Nix file imported by it must be a Derivation or a function that returns a Derivation. Its result is a Derivation(a software package) too.
So what does the Nix file that can be used as a parameter of `pkgs.callPackge` look like? You can take a look at the `hello.nix` `fcitx5-rime.nix` `vscode/with-extensions.nix` `firefox/common.nix` we mentioned earlier, they can all be imported by `pkgs.callPackage`.
When the `xxx.nix` used in `pkgs.callPackge xxx.nix {...}` is a function (most Nix packages are like this), the execution flow is as follows:
1. `pkgs.callPackge xxx.nix {...}` will first `import xxx.nix` to get the function defined in it. The parameters of this function usually have `lib`, `stdenv`, `fetchurl` and other parameters, as well as some custom parameters, which usually have default values.
2. Then `pkgs.callPackge` will first look up the value matching the name from the current environment as the parameter to be passed to the function. parameters like `lib` `stdenv` `fetchurl` are defined in nixpkgs, and they will be found in this step.
3. Then `pkgs.callPackge` will merge its second parameter `{...}` with the attribute set obtained in the previous step, and then pass it to the function imported from `xxx.nix` and execute it.
4. Finally we get a Derivation as the result of the function execution.
2023-06-27 03:31:47 +00:00
The common usage of `pkgs.callPackage` is to import customized Nix packages and used them in Nix Module.
2023-06-27 03:34:28 +00:00
For example, we have customized a NixOS kernel configuration `kernel.nix`, and it uses the SBC's name and kernel source as its variable parameters:
2023-06-27 03:31:47 +00:00
```nix
{
lib,
stdenv,
linuxManualConfig,
src,
boardName,
...
}:
(linuxManualConfig {
version = "5.10.113-thead-1520";
modDirVersion = "5.10.113";
inherit src lib stdenv;
# file path to the generated kernel config file(the `.config` generated by make menuconfig)
#
# here is a special usage to generate a file path from a string
configfile = ./. + "${boardName}_config";
allowImportFromDerivation = true;
})
```
2023-06-27 03:34:28 +00:00
Then we can use `pkgs.callPackage ./kernel.nix {}` in any Nix Module to import and replace any of its parameters:
2023-06-27 03:31:47 +00:00
```nix
{ lib, pkgs, pkgsKernel, kernel-src, ... }:
{
# ......
boot = {
# ......
kernelPackages = pkgs.linuxPackagesFor (pkgs.callPackage ./pkgs/kernel {
src = kernel-src; # kernel source is passed as a `specialArgs` and injected into this module.
boardName = "licheepi4a"; # the board name, used to generate the kernel config file path.
});
# ......
}
```
Just like the example above, we can use `pkgs.callPackage` to pass different `src` and `boardName` to the function defined in `kernel.nix` through `pkgs.callPackage`, so that different kernel packages can be generated.
The `kernel.nix` can be used to adapt to different kernel sources and different development boards by changing the parameters passed to it.
## References
- [Chapter 13. Callpackage Design Pattern - Nix Pills](https://nixos.org/guides/nix-pills/callpackage-design-pattern.html)