nixpkgs mirror (for testing)
github.com/NixOS/nixpkgs
nix
1# Name-based package directories
2
3The structure of this directory maps almost directly to top-level package attributes.
4Add new top-level packages to Nixpkgs using this mechanism [whenever possible](#limitations).
5
6Packages found in the name-based structure are automatically included, without needing to be added to `all-packages.nix`. However if the implicit attribute defaults need to be changed for a package, this [must still be declared in `all-packages.nix`](#changing-implicit-attribute-defaults).
7
8## Example
9
10The top-level package `pkgs.some-package` may be declared by setting up this file structure:
11
12```
13pkgs
14└── by-name
15 ├── so
16 ┊ ├── some-package
17 ┊ └── package.nix
18
19```
20
21Where `some-package` is the attribute name corresponding to the package, and `so` is the lowercase 2-letter prefix of the attribute name.
22
23The `package.nix` may look like this:
24
25```nix
26# A function taking an attribute set as an argument
27{
28 # Get access to top-level attributes for use as dependencies
29 lib,
30 stdenv,
31 libbar,
32
33 # Make this derivation configurable using `.override { enableBar = true }`
34 enableBar ? false,
35}:
36
37# The return value must be a derivation
38stdenv.mkDerivation {
39 # ...
40 buildInputs = lib.optional enableBar libbar;
41}
42```
43
44You can also split up the package definition into more files in the same directory if necessary.
45
46Once defined, the package can be built from the Nixpkgs root directory using:
47```
48nix-build -A some-package
49```
50
51See the [general package conventions](../README.md#conventions) for more information on package definitions.
52
53### Changing implicit attribute defaults
54
55The above expression is called using these arguments by default:
56```nix
57{
58 lib = pkgs.lib;
59 stdenv = pkgs.stdenv;
60 libbar = pkgs.libbar;
61}
62```
63
64But the package might need `pkgs.libbar_2` instead.
65While the `libbar` argument could explicitly be overridden in `all-packages.nix` with `libbar_2`, this would hide important information about this package from its interface.
66The fact that the package requires a certain version of `libbar` to work should not be hidden in a separate place.
67It is preferable to use `libbar_2` as an argument name instead.
68
69This approach also has the benefit that, if the expectation of the package changes to require a different version of `libbar`, a downstream user with an override of this argument will receive an error.
70This is comparable to a merge conflict in git: It's much better to be forced to explicitly address the conflict instead of silently keeping the override - which might lead to a different problem that is likely much harder to debug.
71
72## Manual migration guidelines
73
74Most packages are still defined in `all-packages.nix` and the [category hierarchy](../README.md#category-hierarchy).
75Since it would take a lot of contributor and reviewer time to migrate all packages manually,
76an [automated migration is planned](https://github.com/NixOS/nixpkgs/pull/211832),
77though it is expected to still take some time to get done.
78If you're interested in helping out with this effort,
79please see [this ticket](https://github.com/NixOS/nixpkgs-vet/issues/56).
80
81Since [only PRs to packages in `pkgs/by-name` can be automatically merged](../../CONTRIBUTING.md#how-to-merge-pull-requests-yourself),
82if package maintainers would like to use this feature, they are welcome to migrate their packages to `pkgs/by-name`.
83To lessen PR traffic, they're encouraged to also perform some more general maintenance on the package in the same PR,
84though this is not required and must not be expected.
85
86Note that `callPackage` definitions in `all-packages.nix` with custom arguments should not be removed.
87That is a backwards-incompatible change because it changes the `.override` interface.
88Such packages may still be moved to `pkgs/by-name` however, in order to avoid the slightly superficial choice of directory / category in which the `default.nix` file was placed, but please keep the definition in `all-packages.nix` using `callPackage`.
89See also [changing implicit attribute defaults](#changing-implicit-attribute-defaults).
90
91Definitions like the following however, _can_ be transitioned:
92
93```nix
94# all-packages.nix
95{
96 fooWithBaz = foo.override { bar = baz; };
97}
98```
99
100```nix
101# turned into pkgs/by-name/fo/fooWithBaz/package.nix with:
102{ foo, baz }:
103
104foo.override { bar = baz; }
105```
106
107## Limitations
108
109There are some limitations as to which packages can be defined using this structure:
110
111- Only packages defined using `pkgs.callPackage`.
112 This excludes packages defined using `pkgs.python3Packages.callPackage ...`.
113
114 Instead:
115 - Either change the package definition to work with `pkgs.callPackage`.
116 - Or use the [category hierarchy](../README.md#category-hierarchy).
117
118- Only top-level packages.
119 This excludes packages for other package sets like `pkgs.pythonPackages.*`.
120
121 Refer to the definition and documentation of the respective package set to figure out how such packages can be declared.
122
123## Validation
124
125CI performs [certain checks](https://github.com/NixOS/nixpkgs-vet?tab=readme-ov-file#validity-checks) on the `pkgs/by-name` structure.
126This is done using the [`nixpkgs-vet` tool](https://github.com/NixOS/nixpkgs-vet).
127
128You can locally emulate the CI check using
129
130```
131$ ./ci/nixpkgs-vet.sh master
132```
133
134## Recommendation for new packages with multiple versions
135
136These checks of the `pkgs/by-name` structure can cause problems in combination:
1371. New top-level packages using `callPackage` must be defined via `pkgs/by-name`.
1382. Packages in `pkgs/by-name` cannot refer to files outside their own directory.
139
140This means that outside `pkgs/by-name`, multiple already-present top-level packages can refer to some common file.
141If you open a PR to another instance of such a package, CI will fail check 1,
142but if you try to move the package to `pkgs/by-name`, it will fail check 2.
143
144This is often the case for packages with multiple versions, such as
145
146```nix
147{
148 foo_1 = callPackage ../tools/foo/1.nix { };
149 foo_2 = callPackage ../tools/foo/2.nix { };
150}
151```
152
153The best way to resolve this is to not use `callPackage` directly, such that check 1 doesn't trigger.
154This can be done by using `inherit` on a local package set:
155```nix
156{
157 inherit
158 ({
159 foo_1 = callPackage ../tools/foo/1.nix { };
160 foo_2 = callPackage ../tools/foo/2.nix { };
161 })
162 foo_1
163 foo_2
164 ;
165}
166```
167
168While this may seem pointless, this can in fact help with future package set refactorings,
169because it establishes a clear connection between related attributes.
170
171### Further possible refactorings
172
173This is not required, but the above solution also allows refactoring the definitions into a separate file:
174
175```nix
176{ inherit (import ../tools/foo pkgs) foo_1 foo_2; }
177```
178
179```nix
180# pkgs/tools/foo/default.nix
181pkgs: {
182 foo_1 = callPackage ./1.nix { };
183 foo_2 = callPackage ./2.nix { };
184}
185```
186
187Alternatively using [`callPackages`](https://nixos.org/manual/nixpkgs/unstable/#function-library-lib.customisation.callPackagesWith)
188if `callPackage` isn't used underneath and you want the same `.override` arguments for all attributes:
189
190```nix
191{ inherit (callPackages ../tools/foo { }) foo_1 foo_2; }
192```
193
194```nix
195# pkgs/tools/foo/default.nix
196{ stdenv }:
197{
198 foo_1 = stdenv.mkDerivation {
199 # ...
200 };
201 foo_2 = stdenv.mkDerivation {
202 # ...
203 };
204}
205```
206
207### Exposing the package set
208
209This is not required, but the above solution also allows exposing the package set as an attribute:
210
211```nix
212{
213 foo-versions = import ../tools/foo pkgs;
214 # Or using callPackages
215 # foo-versions = callPackages ../tools/foo { };
216
217 inherit (foo-versions) foo_1 foo_2;
218}
219```