Skip to content

Commit 8a9e206

Browse files
committed
[RFC 0083] common interface package sets
1 parent 123e94a commit 8a9e206

File tree

1 file changed

+202
-0
lines changed

1 file changed

+202
-0
lines changed
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
---
2+
feature: common-interface-package-sets
3+
start-date: 2020-12-19
4+
author: Frederik Rietdijk (@FRidh)
5+
co-authors:
6+
related-issues:
7+
---
8+
9+
# Summary
10+
[summary]: #summary
11+
12+
The Nixpkgs package set consists of a large amount of packages of which a
13+
significant amount of grouped into sub package sets. This RFC recommends a
14+
common interface for these package sets.
15+
16+
# Motivation
17+
[motivation]: #motivation
18+
19+
The Nixpkgs package set consists of a large amount of packages of which a
20+
significant amount of grouped into sub package sets. Sets exist for various
21+
languages, frameworks and plugins.
22+
23+
They are typically grouped together for one of the following two reasons:
24+
- clarity, e.g. because they're written in the same language or framework;
25+
- necessity, e.g. for compatibility reasons.
26+
27+
Over time different methods for defining package sets were created. Currently
28+
multiple methods are in use in Nixpkgs and pull requests are opened to modify
29+
sub package sets interfaces from one kind to another. Not only is this confusing
30+
for users but it also causes trouble; in some cases overriding of derivations
31+
inside a set is not possible or cross-compilation is broken.
32+
33+
This RFC thus aims to unify the package sets to a common interface for the
34+
following reasons:
35+
- simplify usage of package sets and reduce confusion surrounding them;
36+
- single approach for dealing with overrides;
37+
- handle variants of a package set;
38+
- ensure cross-compilation works.
39+
40+
Often one also wants to build an environment with an interpreter or main program
41+
and some additional packages or plugins. This RFC will therefore also recommend
42+
a function each package set should offer for doing so, when appliceable that is.
43+
44+
## Related issues
45+
46+
TODO: refer to these issues in correct place.
47+
48+
- Common override interface derivations https://github.com/NixOS/rfcs/pull/67
49+
- Make PHP packages overrideable https://github.com/NixOS/nixpkgs/pull/107044
50+
- Change in emacs interface https://github.com/NixOS/nixpkgs/pull/107152
51+
- Python package set is not overrideable
52+
https://github.com/NixOS/nixpkgs/issues/44426
53+
- Support `overrideScope'` in Python package set
54+
https://github.com/NixOS/nixpkgs/pull/105374
55+
- Common `overrideArgs` for sub package sets
56+
https://github.com/NixOS/nixpkgs/pull/46842. May be resolved using
57+
`overrideAuto` in https://github.com/NixOS/rfcs/pull/67.
58+
59+
# Detailed design
60+
[design]: #detailed-design
61+
62+
We will now look in more detail at what a common interface should offer.
63+
64+
## Attribute name of the package set: `fooPackages` versus `foo.pkgs`
65+
66+
Two different interfaces are common in Nixpkgs when referring to package sets:
67+
- `fooPackages`
68+
- `foo.pkgs`
69+
70+
TODO which one to pick?
71+
## Variants
72+
Often multiple variants of a package set need to be created. E.g., in case of
73+
emacs or Python there are different versions of the program and each of them
74+
should have their own package set. For this reason it is important that one can
75+
easily create a new variant
76+
77+
```nix
78+
fooPackagesFor = foo: import ./foo-packages.nix { ... };
79+
fooPackages_3_6 = fooPackagesFor foo_3_6;
80+
```
81+
82+
## Set overriding
83+
It should be possible to override packages in a sub package set and have the
84+
other packages in the set take that override into account. To that end, a scope
85+
is created
86+
87+
```nix
88+
lib.makeScope pkgs.newScope (self: with self; {
89+
...
90+
}
91+
```
92+
93+
that can be overridden using `overrideScope'`
94+
95+
```nix
96+
fooPackages_3_6.overrideScope' overrides;
97+
```
98+
99+
where `overrides` is of the form
100+
101+
```nix
102+
(final: previous: { ... })
103+
```
104+
105+
In case one uses overlays with Nixpkgs, one could now make the overrides
106+
composible using
107+
108+
```nix
109+
fooPackages_3_6 = fooPackages_3_6.overrideScope' overrides;
110+
```
111+
112+
## Package overriding
113+
114+
Now that it is possible to override a set, a common interface to overriding the
115+
packages inside the set is needed as well. This is treated in [RFC
116+
67](https://github.com/NixOS/rfcs/pull/67).
117+
118+
## Cross-compilation
119+
120+
For cross-compilation it is important that `callPackage` in the sub package set
121+
has access to the spliced versions of the sub package set. Until recently, there
122+
were no spliced sub package sets in Nixpkgs, but support was added for Python
123+
utilizing the `makeScopeWithSplicing` function. There is [room for
124+
improvement](https://github.com/NixOS/nixpkgs/pull/105374).
125+
126+
An important aspect for making this work is that, when constructing the package
127+
set, it needs to know its own top-level attribute.
128+
129+
...
130+
131+
132+
To support nested package sets, the full attribute path is needed, including
133+
dots.
134+
135+
```nix
136+
`fooPackages_3_6.subFooPackages_2_5`
137+
```
138+
139+
## Single function for creating a package set
140+
141+
To ease the creation of a package set, a single function is proposed for
142+
creating a set given a main program and an attribute name.
143+
144+
145+
```nix
146+
makePackageSet = ...
147+
```
148+
149+
## Composing an environment
150+
151+
Thus far we considered building a package set and overriding it. Somewhat
152+
orthogonal yet still commonly needed, is a method to compose an environment of
153+
packages inside the package set.
154+
155+
Starting with Haskell and later adopted by other package sets is a
156+
`withPackages(ps: [...])` function that allows you to compose an environment with chosen
157+
packages from the set.
158+
159+
This RFC recommends each package set should have such a function, in case it is
160+
appliceable. An example of where it would not make sense to include such a
161+
function is in case of a [Qt package
162+
set](https://github.com/NixOS/nixpkgs/pull/102168) because you would not be
163+
interested in having a Qt with libraries during runtime and nothing else.
164+
165+
Haskell introduced the function as part of its package set, that is, one uses
166+
`haskellPackages.ghcWithPackages (ps: [...]). Some time later Python added such
167+
function, but as part of the interpreter `python3.withPackages(ps: [...])`.
168+
Since then, many other sets also added `withPackages` as part of the
169+
interpreter or main program.
170+
171+
### `fooPackages` versus `foo.pkgs` again...
172+
173+
TODO
174+
175+
Unfortunately, having `withPackages` as part of the main program makes it
176+
somewhat more difficult to use it when overrides are needed as well. One would have to write
177+
178+
```nix
179+
(foo_3_6.pkgs.overrideScope' overrides).foo.withPackages(ps: [...])
180+
```
181+
Indeed, the `withPackages` of the main program inside the sub set needs to be used. Using
182+
183+
TODO the actual recommendation
184+
185+
# Examples and Interactions
186+
187+
188+
# Drawbacks
189+
[drawbacks]: #drawbacks
190+
191+
192+
193+
# Alternatives
194+
[alternatives]: #alternatives
195+
196+
# Future work
197+
[future]: #future-work
198+
199+
- Document the recommended interface in the Nixpkgs manual.
200+
- Adopt the recommended interface in existing package sets in Nixpkgs.
201+
- Encourage tools that create package sets, e.g. from lock files, to also adopt
202+
this interface.

0 commit comments

Comments
 (0)