-
-
Notifications
You must be signed in to change notification settings - Fork 14.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
pkgs/top-level: make package sets composable #303849
base: master
Are you sure you want to change the base?
Conversation
Eval is broken :( |
That said, this is generally good stuff and we should land this (though maybe after 24.05?) |
I don't have time to review this right now but I just want to say, thank you so much for writing this, and your commit messages are great! |
I haven't been able to find out why, yet :/ |
Will change to "draft" until I have the time to figure that out. |
10fb3c4
to
1039e99
Compare
I rebased on latest master and should have fixed eval along the way. |
1039e99
to
fc5dab0
Compare
Improved the commit messages, fixed another eval failure and added another commit to do the following, as mentioned above:
Let's see where ofborg fails this time. |
fc5dab0
to
8ce3fca
Compare
Rebased and cherry-picked #314845. This makes |
eval passes now. Ready for review. Please ignore the first commit (see other comment). |
Thank for doing a very thorough job documenting your work, @wolfgangwalther, but I am a little worried about passing this information. it was originally very intentional that I transformed the ugly/bad I think I see why you are doing this, but another way to look at this is that having the other package sets mashed into |
@Ericson2314 I'm not sure what the takeaway from this is. Are you saying that package sets should not be composed? I.e. we should only have (example) Clearly the status-quo, where it's possible to call them, but they only compose in parts, but not in others, is a problem. |
Overall, I can find 5 different approaches how to do deal with those package sets:
Obviously, I'm in favor of the last option. Once we agree on where this should go, we can look into how to make this nicer architecturally. |
8ce3fca
to
8664455
Compare
I have changed the approach from "pass localSystem and crossSystem to stage.nix" to "make nixpkgsFun itself composable". So "dealing with the bad/ugly localSystem/crossSystem" only happens in default.nix now - stage.nix is a lot cleaner than before. @Ericson2314 Do you like this approach better? |
pkgsMusl seems broken on NixOS: $ nix repl github:wolfgangwalther/nixpkgs/compose-pkgs-sets
> system = lib.nixosSystem { system = "x86_64-linux"; modules = []; }
> system.pkgs.pkgsMusl.stdenv.hostPlatform.libc
"glibc" nixpkgs master prints "musl" as expected. |
Hmm... I do this and get the expected result:
Not familiar too much with Unfortunately, |
It's the same thing as evaluating a nixos system which you can do with
|
Ah, thanks. I can reproduce it with that, indeed. Really odd. Will look into it on the weekend. |
This can be reduced down to this:
Imho, this is an existing bug in |
This removes all specific references to pkgsCross or pkgsi686Linux, because they have become outdated with the addition of many more package sets.
…e bottom No change, just move appendOverlays and extend to the bottom, since they will be changed much less often. This makes it easier to compare the other package sets side-by-side.
Sharing a first piece of common code between all package sets makes it easier to maintain and less likely to introduce a new package set without this.
@m-bdf thanks for your feedback, I applied the suggestion for the tests.
This works now:
Not much we can do about systems.elaborate, it's not designed to return "correct" systems with arbitrary overrides applied. |
ccb185a
to
6693a00
Compare
# Basic test for idempotency of the package set, i.e: | ||
# Applying the same package set twice should work and | ||
# not change anything. | ||
isIdempotent = set: discardEvaluationErrors (pkgs.${set}.stdenv == pkgs.${set}.${set}.stdenv); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
stdenv
is a derivation, and ==
on derivations is limited to outPath
.
So this would be equivalent and avoid confusion:
isIdempotent = set: discardEvaluationErrors (pkgs.${set}.stdenv == pkgs.${set}.${set}.stdenv); | |
isIdempotent = set: discardEvaluationErrors (pkgs.${set}.stdenv.outPath == pkgs.${set}.${set}.stdenv.outPath); |
However, I think you do want to check more:
isIdempotent = set: discardEvaluationErrors (pkgs.${set}.stdenv == pkgs.${set}.${set}.stdenv); | |
isIdempotent = set: discardEvaluationErrors (pkgs.${set}.stdenv.outPath == pkgs.${set}.${set}.stdenv.outPath | |
&& pkgs.${set}.stdenv.hostPlatform == pkgs.${set}.${set}.stdenv.hostPlatform | |
&& pkgs.${set}.stdenv.buildPlatform == pkgs.${set}.${set}.stdenv.buildPlatform | |
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm.. according to the test failures I got during development, I assumed the outPath changes when host or build platform change. Is that not correct?
I tried adding the hostPlatform & buildPlatform checks. Instead of ==
, I had to use lib.systems.equals
. I didn't get any test failures this way. This doesn't mean I don't need those changes, but do you have any example where a change to hostPlatform / buildPlatform would not affect stdenv's outPath?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to support the idea that those platforms should affect stdenv's outpath:
nixpkgs/pkgs/stdenv/generic/default.nix
Line 167 in 48d5c5f
inherit buildPlatform hostPlatform targetPlatform; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now, I made the .outPath
comparison explicit, but didn't add the platform checks, yet.
Edit: I reverted the change to use outPath, because nixfmt then requires it to be split across two lines awkwardly. This'd be a net-negative for readability.
|
||
let | ||
# To silence platform specific evaluation errors | ||
discardEvaluationErrors = e: (builtins.tryEval e).success -> e; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extensive use of this makes the test less effective.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Without those, I have errors like this quickly:
error: x86_64 Darwin package set can only be used on Darwin systems.
Those are the errors thrown in pkgs/top-level/stage.nix
. Any idea how I could target those more specifically - without replicating the logic around those into the tests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I went through the code again and I think discardEvaluationErrors
does not necessarily make the test less effective. In fact it makes it more specific. The calls to this function are placed only around conditionals, so the evaluation errors can only come from evaluating those package sets.
These tests are not meant to test the evaluation of each package set, but to test the composability of them, i.e. they are supposed to test the code in stage.nix
, not further downstream. If stdenv
for a certain package set is broken, this is not the place to test it, imho.
c472e79
to
0101943
Compare
This adds some basic tests to compose package sets. The cases that are currently broken are commented out, they include things like: - pkgsStatic.pkgsMusl losing the isStatic flag - pkgsCross.ppc64-musl.pkgsMusl losing the gcc.abi setting - pkgsCross.mingwW64.pkgsStatic losing the config string - pkgsLLVM.pkgsMusl losing the useLLVM flag - pkgsLLVM.pkgsStatic losing the useLLVM flag - pkgsLLVM.pkgsi686Linux losing the useLLVM flag And probably more.
Passing the elaborated system defeats what pkgs/top-level/default.nix tries to do: Pass only the original args and let defaults be inferred. The underlying problem is that lib.systems.elaborate can not deal with arbitrary overrides, but will often return an inconsistent system description when partially overriding some values. This becomes most prominent if trying to override an already elaborated system.
The various pkgsXYZ top-level package sets did not pass localSystem / crossSystem to lower levels, so far. This change propagates original arguments to lower levels, which include the overrides made by an upper package sets. There is an extensive test-suite to test various combinations of package sets in pkgs/test/top-level. There are a few basic promises made: - Package sets must be idempotent. pkgsMusl.pkgsMusl === pkgsMusl. - Once pkgsCross is used any subsequent package sets should affect the **host platform** and not the build platform. Examples: - pkgsMusl.pkgsCross.aarch64-multiplatform is a cross compilation from musl to glibc/aarch64 - pkgsCross.aarch64-multiplatform.pkgsMusl is a cross compilation to musl/aarch64 - Modifications from an earlier layer should not be lost, unless explicitly overwritten. Examples: - pkgsStatic.pkgsMusl should still be static. - pkgsStatic.pkgsCross.gnu64 should be static, but with glibc instead of musl. Exceptions / TODOs: - pkgsExtraHardening is currently not idempotent, because it applies the same flags over and over again. Supersedes NixOS#136549 Resolves NixOS#114510 Resolves NixOS#212494 Resolves NixOS#281596
When using pkgsCross with a system that ends up the same as the localSystem, then modifications for package sets like pksgMusl need to be done for **both** localSystem and crossSystem. Consider the following on x86_64-linux: pkgsCross.gnu64.pkgsMusl Before this change, this would result in a musl buildPlatform, but a gnu hostPlatform. This breaks the promise of "stacking" package sets on top of each other. After this change, it results in a musl buildPlatform and a musl hostPlatform. This works better. One could expect this to result in the same as pkgsCross.musl64, i.e. a gnu buildPlatform and a musl hostPlatform, however I couldn't get this to work without increasing memory usage for ci/eval by many, many GB. This is caused by usage of pkgsi686Linux inside the main package set, which follows the same hybrid pattern.
0101943
to
7a9cb10
Compare
Description of changes
The various
pkgsXYZ
top-level package sets did not passlocalSystem
/crossSystem
options to lower levels, so far. This change propagates the original arguments, i.e.localSystem0
/crossSystem0
to lower levels. Those include the overrides made by an upper package set.Example:
pkgsStatic
addscrossSystem = { isStatic = true }
.pkgsStatic.pkgsMusl
previously lost this setting, because it didn't propagatecrossSystem0
, yet.The first commit removes / rewrites some outdated comments, which referred to the cross and i686 package sets. Meanwhile, we have a lot more, so I rewrote those comments to not say anything about specific sets anymore.
The second commit adds some tests to confirm composability of package sets. This helped me coming up with the fixes, I'm not sure whether it should be kept. It takes about 8-9 seconds for me to run. It also helps showing what the remaining commits fix by uncommenting the previously broken tests.
The remaining commits fix those composability issues. This:
One open question for me is how to deal withpkgsXYZ.pkgsCross
. This has practical challenges (#114510), but is also conceptually unsound: In a waypkgsCross
expects to resetcrossSystem
from scratch, because the whole point about this layer is to start with "well known" example configurations. IMHO, it's fine to make modifications on top of that. e.g.pkgsCross.XYZ.pkgsLLVM
orpkgsCross.XYZ.pkgsStatic
, but it makes little sense to havepkgsLLVM.pkgsCross...
orpkgsStatic.pkgsCross...
. Probably completely unusable ispkgsCross.XYZ.pkgsCross.ABC
.One idea would be to just restrictpkgsCross
to be used at the top-level, for example by adding something like this in each package set, includingpkgsCross
itself: [...]That would also disallowpkgsMusl.pkgsCross.XYZ
, which I think is about the only remotely reasonable use-case here: "cross compiling from a native musl environment". I'm not sure whether anyone uses that, though, and whether it's worth supporting at all.Things done
nix.conf
? (See Nix manual)sandbox = relaxed
sandbox = true
nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD"
. Note: all changes have to be committed, also see nixpkgs-review usage./result/bin/
)Add a 👍 reaction to pull requests you find important.