nixpkgs mirror (for testing) github.com/NixOS/nixpkgs
nix
at python-updates 219 lines 7.6 kB view raw view rendered
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```