Skip to content

lib.systems: deprecate == comparison between elaborated platforms#380005

Open
MattSturgeon wants to merge 6 commits intoNixOS:masterfrom
MattSturgeon:elaborate/inputs
Open

lib.systems: deprecate == comparison between elaborated platforms#380005
MattSturgeon wants to merge 6 commits intoNixOS:masterfrom
MattSturgeon:elaborate/inputs

Conversation

@MattSturgeon
Copy link
Contributor

@MattSturgeon MattSturgeon commented Feb 7, 2025

As suggested by @wolfgangwalther #380005 (comment), I've scaled back this PR to focus on the treewide deprecation of == comparison between elaborated platform attrsets. The other changes are replaced by #380342.

This is in contrast to the previous effort to fully support == with elaborated platform attrsets: #238331. Also related: #278001.

A "backwards compatibility" item has been added to the release notes.

Added equals and notEquals functions to elaborated systems. This makes replacing == and != usage simpler, and also provides a convenient alternative to using lib.systems.equals directly.

Added an extra attr (warnAboutEquality) to elaborated systems that exists only to produce a warning when evaluated. This is intended to detect == comparison being used with platform attrsets, suggested by @roberth #380005 (comment).

This approach isn't perfect, because it is only evaluated if the == comparison has not already short-circuited. E.g. if the attr-count is different or some other difference has already been found before getting to the warnAboutEquality attr. These limitations were raised by @wolfgangwalther #380005 (comment) and were also discussed in this note.

The treewide change has been done using some regex search/replace together with vim's quickfix list and some manual checking. It covers ~600 changes, so I haven't been able to check each individual replacement in detail. As mentioned by @roberth, many of the replacements could probably use canExec instead of equals, but that change is not in scope for this PR.

Old summary

Intended to enable composition of package sets by preserving the original un-elaborated arguments passed to lib.systems.elaborate.

This PR does not actually make package sets composable, but it is intended that the implementation proposed here will enable @wolfgangwalther to revisit their earlier work in #303849 and #376988 without needing to make changes to the public API or the nixpkgs nixos module.

Adds:

  • lib.systems.isElaborated
  • A _type tag for elaborated systems
  • input attr on elaborated systems
  • lib.systems.equals ignores the new input attr

Additionally:

  • added equals and notEquals "method" attr-functions for convenience, and to allow comparison without needing access to lib
  • treewide migration from == -> <platform>.equals
  • elaborated platforms now warn when fully evaluated, in order to warn against using ==

cc @wolfgangwalther @roberth

Things done

  • Built on platform(s)
    • x86_64-linux
    • aarch64-linux
    • x86_64-darwin
    • aarch64-darwin
  • For non-Linux: Is sandboxing enabled in nix.conf? (See Nix manual)
    • sandbox = relaxed
    • sandbox = true
  • Tested, as applicable:
  • Tested compilation of all packages that depend on this change using nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD". Note: all changes have to be committed, also see nixpkgs-review usage
  • Tested basic functionality of all binary files (usually in ./result/bin/)
  • 25.05 Release Notes (or backporting 24.11 and 25.05 Release notes)
    • (Package updates) Added a release notes entry if the change is major or breaking
    • (Module updates) Added a release notes entry if the change is significant
    • (Module addition) Added a release notes entry if adding a new NixOS module
  • Fits CONTRIBUTING.md.

Add a 👍 reaction to pull requests you find important.

@github-actions github-actions bot added the 6.topic: lib The Nixpkgs function library label Feb 7, 2025
@github-actions github-actions bot added 10.rebuild-darwin: 1 This PR causes 1 package to rebuild on Darwin. 10.rebuild-darwin: 1-10 This PR causes between 1 and 10 packages to rebuild on Darwin. 10.rebuild-linux: 1-10 This PR causes between 1 and 10 packages to rebuild on Linux. labels Feb 7, 2025
@nix-owners nix-owners bot requested a review from infinisil February 7, 2025 06:15
@MattSturgeon MattSturgeon force-pushed the elaborate/inputs branch 2 times, most recently from c12ddc8 to e105d83 Compare February 7, 2025 06:18
Copy link
Member

@roberth roberth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My thoughts. I'm not the most knowledgeable person on the subject of these platform values, but I'd like to support you and @wolfgangwalther if possible.

@github-actions github-actions bot added 6.topic: python Python is a high-level, general-purpose programming language. 6.topic: nixos Issues or PRs affecting NixOS modules, or package usability issues specific to NixOS 6.topic: haskell General-purpose, statically typed, purely functional programming language 6.topic: qt/kde Object-oriented framework for GUI creation 8.has: module (update) This PR changes an existing module in `nixos/` 6.topic: rust General-purpose programming language emphasizing performance, type safety, and concurrency. 6.topic: golang Go is a high-level general purpose programming language that is statically typed and compiled. 6.topic: ruby A dynamic, open source programming language with a focus on simplicity and productivity. 6.topic: vim Advanced text editor 6.topic: ocaml OCaml is a general-purpose, high-level, multi-paradigm programming language. 6.topic: stdenv Standard environment labels Feb 7, 2025
Copy link
Member

@FliegendeWurst FliegendeWurst left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another merge conflict appeared. LGTM otherwise.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure why the example replacement is replacing equals with canExecute.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's one possible replacement for some cases, because often enough the == check is just trying to prevent "real cross" scenarios, where you can't execute the binaries on your build system. So for a lot of cases, this could be a better replacement, but it might not always be correct.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know of many packages where the build system just doesn't understand the distinction between build and host. For such cases an equality check makes sense.

@wegank wegank added the 12.approvals: 2 This PR was reviewed and approved by two persons. label Apr 18, 2025
@wolfgangwalther
Copy link
Contributor

To move this PR forward, I'd like to focus on the one thing that should be discussed most:

This is in contrast to the previous effort to fully support == with elaborated platform attrsets: #238331. Also related: #278001.

Previously, the plan has been to get rid of all functions in elaborated platforms to eventually support == properly. This PR moves away from this approach.

Are there any objections to this?

If not, I think we should ship the deprecation with 25.05. I would not consider the deprecation itself a breaking change, so I don't think we are bound to the 23rd as a date. Please voice your concerns, if any, until next Friday, the 25th of April.

@emilazy
Copy link
Member

emilazy commented Apr 19, 2025

Sorry for taking so long to get around to this.

My tl;dr take:

  • It’s unfortunate that Nix == behaves so incoherently for equality on objects‐with‐methods like this. The hack to cause a warning or error is cool, but short‐circuiting means it will never catch things reliably. That makes me inclined to approaches that separate out data and functions where possible, as sad a limitation as that is.

  • I also think it’s valuable to be able to serialize platform definitions to JSON, etc.

  • However, you’re the ones who have put a ton of work into cleaning this stuff up, and I don’t know if there’s any easy way to get the desired behaviour with my preferred approach, so I don’t want my cheap takes to override your hard work; this is just my 2¢.

  • In the long run, I quite strongly believe that we should separate out inputs to platform elaboration from outputs. Currently we have one monolithic structure that gets “mutated” with outputs, and some things you specify on input get ignored, some produce incoherent combinations, and so on. It seems to me that we need separate types and interfaces for things you can use to specify a platform to Nixpkgs and computed values Nixpkgs derives from a platform specification. There will be overlap, of course, but to me this lack of separation is the root cause of all the problems we’ve had around this. I believe addressing this would probably allow us to have a plain‐old‐data approach while being able to adjust platform configurations by modifying the inputs rather than the outputs.

  • Honestly I’m not sure how much actually comparing platforms for exact equality makes sense as an operation in general…

@MattSturgeon
Copy link
Contributor Author

Sorry for taking so long to get around to this.

I don’t want my cheap takes to override your hard work; this is just my 2¢.

I for one value your input! ❤️


  • It’s unfortunate that Nix == behaves so incoherently for equality on objects‐with‐methods like this.

Agreed. It's also worth noting that == is not just an issue because of functions, but also because of wanting to do things like separate input and output attrs within the platform. Two platforms with the same outputs should be considered equal regardless of their inputs.


The hack to cause a warning or error is cool, but short‐circuiting means it will never catch things reliably.

Yes, it's sad that we can't find a reliable way to print a warning on == use, but I think it is good enough to catch most cases.

  • I also think it’s valuable to be able to serialize platform definitions to JSON, etc.

This would be possible with a lib.systems.toJSON function that uses the same removeUnwanted as equals does. Sad that you can't directly pass the platform to builtins.toJSON, but I don't see a way around this.


That makes me inclined to approaches that separate out data and functions where possible, as sad a limitation as that is.

  • In the long run, I quite strongly believe that we should separate out inputs to platform elaboration from outputs.

That would also require the same == deprecation, assuming inputs and outputs were both stored within the platform structure.

#380342 is attempting to do something similar by capturing inputs in the override function's scope.

  • Honestly I’m not sure how much actually comparing platforms for exact equality makes sense as an operation in general…

👍

@ofborg ofborg bot removed the 2.status: merge conflict This PR has merge conflicts with the target branch label Apr 29, 2025
@github-actions github-actions bot added 10.rebuild-linux: 1-10 This PR causes between 1 and 10 packages to rebuild on Linux. and removed 10.rebuild-linux: 11-100 This PR causes between 11 and 100 packages to rebuild on Linux. labels Apr 29, 2025
@MattSturgeon

This comment was marked as resolved.

@MattSturgeon

This comment was marked as outdated.

MattSturgeon and others added 6 commits May 1, 2025 00:00
Allows replacing `lib.systems.equals foo bar` with `foo.equals bar`.

This is useful when `lib` isn't readily available, and is often less
verbose.
In preparation for deprecating `==` usage on platform attrs.
`(elaborated platform) == "string"` will always be false. This was
probably intended as `(elaborated platform).system == "string"`.

That said, this should usually be replaced with checking the relevant
boolean attributes, such as `isLinux` or `isDarwin`.
Added `warnAboutPlatformEquals` to elaborated platforms.

This new attr prints a warning when evaluated. This is intended to
detect `==` comparison being used with platform attrsets.

This isn't perfect, because it is only evaluated if the `==` comparison
has not already short-circuited. E.g. if the attr-count is different or
some other difference has already been found before getting to the
`warnAboutPlatformEquals` attr.

Added a "backwards compatibility" item to the release notes.

Co-authored-by: Robert Hensing <[email protected]>
A `removeAttrs` call was added by 4eca30d
We may as well use it to simplify the test's implementation.
@emilazy
Copy link
Member

emilazy commented May 16, 2025

That would also require the same == deprecation, assuming inputs and outputs were both stored within the platform structure.

(FWIW, explicitly not mixing them was my intention – it makes sense to me to separate inputs and computed values, because that is exactly what lets you compute new values from a modified input. However I realize that would be a considerably bigger change to disentangle all this stuff.)

@wolfgangwalther
Copy link
Contributor

However I realize that would be a considerably bigger change to disentangle all this stuff.

It would. I'm still exploring the idea lately, thus I haven't acted here, yet.

@wegank wegank added the 2.status: merge conflict This PR has merge conflicts with the target branch label May 17, 2025
@nixpkgs-ci nixpkgs-ci bot added the 2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md label Nov 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

2.status: merge conflict This PR has merge conflicts with the target branch 2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md 6.topic: games Gaming on NixOS 6.topic: golang Go is a high-level general purpose programming language that is statically typed and compiled. 6.topic: haskell General-purpose, statically typed, purely functional programming language 6.topic: lib The Nixpkgs function library 6.topic: llvm/clang Issues related to llvmPackages, clangStdenv and related 6.topic: lua Lua is a powerful, efficient, lightweight, embeddable scripting language. 6.topic: nixos Issues or PRs affecting NixOS modules, or package usability issues specific to NixOS 6.topic: nodejs Node.js is a free, open-source, cross-platform JavaScript runtime environment 6.topic: ocaml OCaml is a general-purpose, high-level, multi-paradigm programming language. 6.topic: python Python is a high-level, general-purpose programming language. 6.topic: qt/kde Object-oriented framework for GUI creation 6.topic: ruby A dynamic, open source programming language with a focus on simplicity and productivity. 6.topic: rust General-purpose programming language emphasizing performance, type safety, and concurrency. 6.topic: stdenv Standard environment 6.topic: systemd Software suite that provides an array of system components for Linux operating systems. 6.topic: TeX Issues regarding texlive and TeX in general 6.topic: vim Advanced text editor 6.topic: zig Zig is an imperative, general-purpose, statically typed, compiled system programming language. 8.has: documentation This PR adds or changes documentation 8.has: module (update) This PR changes an existing module in `nixos/` 10.rebuild-darwin: 1-10 This PR causes between 1 and 10 packages to rebuild on Darwin. 10.rebuild-darwin: 1 This PR causes 1 package to rebuild on Darwin. 10.rebuild-linux: 1-10 This PR causes between 1 and 10 packages to rebuild on Linux. 12.approvals: 2 This PR was reviewed and approved by two persons.

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

9 participants