Skip to content

lib.systems: introduce toolchain, cc, and bintools attributes#365057

Open
RossComputerGuy wants to merge 3 commits intoNixOS:masterfrom
RossComputerGuy:feat/toolchain-attrs
Open

lib.systems: introduce toolchain, cc, and bintools attributes#365057
RossComputerGuy wants to merge 3 commits intoNixOS:masterfrom
RossComputerGuy:feat/toolchain-attrs

Conversation

@RossComputerGuy
Copy link
Member

@RossComputerGuy RossComputerGuy commented Dec 13, 2024

Things done

Replaces useLLVM, useArocc, and useZig with toolchain, cc, linker, and bintools attributes. This might not produce any rebuilds but we'll see. This has the advantage of preventing using${compiler} flags from colliding and not working correctly if we were to stack multiple pkgs* together.

  • 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 6.topic: python Python is a high-level, general-purpose programming language. 6.topic: rust General-purpose programming language emphasizing performance, type safety, and concurrency. 6.topic: windows Running, or buiding, packages on Windows 6.topic: stdenv Standard environment 6.topic: systemd Software suite that provides an array of system components for Linux operating systems. 6.topic: lib The Nixpkgs function library 6.topic: llvm/clang Issues related to llvmPackages, clangStdenv and related labels Dec 13, 2024
@RossComputerGuy RossComputerGuy force-pushed the feat/toolchain-attrs branch 3 times, most recently from 7a3eca0 to 2a005fa Compare December 14, 2024 00:20
@github-actions github-actions bot added 10.rebuild-darwin: 11-100 This PR causes between 11 and 100 packages to rebuild on Darwin. 10.rebuild-linux: 11-100 This PR causes between 11 and 100 packages to rebuild on Linux. labels Dec 14, 2024
@RossComputerGuy RossComputerGuy force-pushed the feat/toolchain-attrs branch 2 times, most recently from 9c8b44b to f6da63d Compare December 14, 2024 00:41
@github-actions github-actions bot added 10.rebuild-darwin: 5001+ This PR causes many rebuilds on Darwin and must target the staging branches. and removed 10.rebuild-darwin: 11-100 This PR causes between 11 and 100 packages to rebuild on Darwin. labels Dec 14, 2024
@tomberek
Copy link
Contributor

The main idea and motivation is in: pkgs/stdenv/cross/default.nix

@github-actions github-actions bot added 10.rebuild-darwin: 11-100 This PR causes between 11 and 100 packages to rebuild on Darwin. and removed 10.rebuild-darwin: 5001+ This PR causes many rebuilds on Darwin and must target the staging branches. labels Dec 14, 2024
@RossComputerGuy RossComputerGuy force-pushed the feat/toolchain-attrs branch 2 times, most recently from 10cd2ba to 2b4d320 Compare December 14, 2024 01:33
@github-actions github-actions bot added 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. and removed 10.rebuild-darwin: 11-100 This PR causes between 11 and 100 packages to rebuild on Darwin. 10.rebuild-linux: 11-100 This PR causes between 11 and 100 packages to rebuild on Linux. labels Dec 14, 2024
@RossComputerGuy RossComputerGuy marked this pull request as ready for review December 14, 2024 01:47
Copy link
Contributor

@K900 K900 left a comment

Choose a reason for hiding this comment

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

ack, would be nice to make this rebuild 0

@RossComputerGuy
Copy link
Member Author

@K900 there was a typo with xwayland, that should be fixed now. It'd be great if we can get this PR through before it becomes more work to rebase.

@RossComputerGuy
Copy link
Member Author

Rebasing, we also have an stdenv board now. I hope this doesn't stall out again because there's a bunch of conflicts and I don't want to rebase this regularly.

Copy link
Contributor

@philiptaron philiptaron left a comment

Choose a reason for hiding this comment

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

Thanks for your work here Tristan. I'm looking to @emilazy to give the ✅ , but I think we are agreed:

  1. Using well-known strings with symbolic meaning is the right direction, rather than is* and use* functions attached to the stdenv.
  2. Splitting apart the concept of the "toolchain" into "cc", "bintools", "cxxlib", "unwinderlib", "rtlib", and "linker" allows derivations to tune their behavior wisely in the face of the combinatorial explosion of possibilities.
  3. We should expect to continue to evolve this system over the course of the next few releases as the codebase adopts and reacts to these well-known strings -- and introduces more, because the innovation train isn't stopping soon.

I'd like to do a build on staging once the merge conflicts are resolved and at least one of @reckenrode or @emilazy accepts, then merge.

What say you all?

Copy link
Contributor

Choose a reason for hiding this comment

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

Not blocking:

If (lib.listToAttrs (lib.map (key: lib.nameValuePair key final.${key}) (lib.attrNames toolchain))) were extracted to a let binding, we could write a good assertion message here.

Copy link
Member Author

Choose a reason for hiding this comment

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

This might be fine as is. I'm not sure, maybe just a comment would be okay? Let's see what others think.

Copy link
Member

Choose a reason for hiding this comment

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

I am mostly worried about whether elaborate is in the hot path of anything. I think that since these values didn’t exist before it’s okay if the error message is bad for now. assert toolchain == lib.mapAttrs (key: _: final.${key}) toolchain seems better and surely faster, regardless.

Copy link
Member Author

Choose a reason for hiding this comment

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

I am mostly worried about whether elaborate is in the hot path of anything. I think that since these values didn’t exist before it’s okay if the error message is bad for now.

I think the people who tend to change these sorts of things are in the minority. They likely would be in a Matrix chat one of us are in anyway so clarification on the failure is possible there. We shouldn't rely on that but I don't see many people utilizing this feature until it is flushed out more.

assert toolchain == lib.mapAttrs (key: _: final.${key}) toolchain seems better and surely faster, regardless.

Oh yeah, that is a better way of checking.

Copy link
Contributor

Choose a reason for hiding this comment

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

me getting confused: why would this be the hostPlatform and not the buildPlatform's linker?

Copy link
Member Author

Choose a reason for hiding this comment

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

According to https://nixos.org/manual/nixpkgs/stable/#ssec-cross-platform-parameters, host is the platform where things run. The things we run are being built with a different linker. crossPlatform in nixpkgs goes to hostPlatform and targetPlatform.

Copy link
Contributor

Choose a reason for hiding this comment

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

this file in particular looks a lot better

Copy link
Contributor

Choose a reason for hiding this comment

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

I like these changes a lot.

@RossComputerGuy
Copy link
Member Author

Considering the size of this PR, complexity, available time, and other factors I think this should be fine as is. We always can work on improving this with additional work. This is something I very much would like to get into 25.05 so I can work on other work like reworking the CPU model support and going towards LLVM bootstrapping inside the stdenv.

I know @philiptaron mentioned he'll start a build up this weekend so we'll see what happens from that.

@emilazy
Copy link
Member

emilazy commented Mar 20, 2025

I think that a PR being huge and complex and having limited available qualified reviewer time are the opposite of reasons to rush a PR…

I still intend to try and find the time to review this over the weekend. However, I continue to think it would be best for everyone to split it up into stages as I previously recommended, since this is still only part of the picture as it is. Landing in 25.05 or not shouldn’t matter for follow‐up work, since these are purely read‐only properties that wouldn’t be exposed interfaces for platform specification or lead to the deprecation of the existing useLLVM etc. until they can be properly wired up to the bootstrap as discussed.

@RossComputerGuy
Copy link
Member Author

Ok, I've split it into just the first commit as a MVP for this feature. This likely will be split into 4 or 6 subsequent PR's.

Copy link
Member

@emilazy emilazy left a comment

Choose a reason for hiding this comment

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

Thanks, I appreciate you splitting off the migration changes since it’ll make them easier to review without blocking this improvement! It looks good to me now modulo a few nits.

Comment on lines 134 to 125
Copy link
Member

Choose a reason for hiding this comment

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

Will this not override the input when these are set? (Might just be final being named confusingly…)

Copy link
Member Author

Choose a reason for hiding this comment

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

No because args is merged on top, that's how libc, isStatic, and a bunch of other things work.

Comment on lines 103 to 115
Copy link
Member

Choose a reason for hiding this comment

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

I think this needs to stay outside of toolchain, since overriding it was already technically “supported” (regardless of whether it actually did anything useful) so it’s a breaking change to include it in the checks, sadly.

Copy link
Member Author

Choose a reason for hiding this comment

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

Alright, understandable.

Comment on lines 90 to 92
Copy link
Member

Choose a reason for hiding this comment

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

I think this needs a cxxrtlib to go with it, per #365057 (comment).

Copy link
Member Author

Choose a reason for hiding this comment

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

Alright, should we imply the cxxrtlib based on the cxxlib or should it be based on the "toolchain" in use?

Comment on lines 94 to 101
Copy link
Member

Choose a reason for hiding this comment

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

I think this and maybe other things might be wrong for MinGW + threads + etc., but I’m not sure what would be right and it can probably wait until this work actually starts touching bootstrap in a way that will flag it up.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, I think @Ericson2314 would know? However, he can be busy and difficult to get ahold of sometimes. If he can clarify like before the end of the week then I think we can go from there but if it's longer than a week then follow up PR's can fix it.

Copy link
Member

Choose a reason for hiding this comment

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

I am mostly worried about whether elaborate is in the hot path of anything. I think that since these values didn’t exist before it’s okay if the error message is bad for now. assert toolchain == lib.mapAttrs (key: _: final.${key}) toolchain seems better and surely faster, regardless.

@RossComputerGuy
Copy link
Member Author

Thank you @emilazy, I've addressed the feedback now.

@nix-owners
Copy link

nix-owners bot commented Apr 5, 2025

The PR's base branch is set to master, but 932 commits from the python-updates branch are included. Make sure you know the right base branch for your changes, then:

  • If the changes should go to the python-updates branch, change the base branch to python-updates
  • If the changes should go to the master branch, rebase your PR onto the merge base with the master branch:
    # git rebase --onto $(git merge-base upstream/master HEAD) $(git merge-base upstream/python-updates HEAD)
    git rebase --onto effac2a6624f7486f081f59e74578203fc1596d3 f9cfc40c66860d770edc93fc630b54bedf103c03
    git push --force-with-lease

@RossComputerGuy
Copy link
Member Author

Accidentally did maintainers/scripts/auto-rebase/run.sh upstream/staging.

@nixos-discourse
Copy link

This pull request has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/prs-ready-for-review/3032/5394

@RossComputerGuy
Copy link
Member Author

I've realized that this might be necessary to make crossStdenv since it would make overriding the toolchain inside the stdenv easier. I have #409851 which implements some of the new logic this PR allows for.

Copy link
Member

@emilazy emilazy left a comment

Choose a reason for hiding this comment

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

Thanks, this looks like a good basis for migrating checks and then the bootstrap. A few details left but I think we can land this soon.

There is one design point I am still unsure about, which is the stringly‐typed nature of the API. Using the cxx vs. c++ ambiguity as an example, a check like stdenv.hostPlatform.cxxlib == "libc++" would be silently wrong right now. That might just be part of the Nix experience, but it is possible we could do better and make this less error‐prone – e.g. expose something stdenv.hostPlatform.cxxlib == lib.toolchain.cxxlib.libcxx to compare against, or lib.toolchain.isLibcxx stdenv.hostPlatform.

Maybe the existing lib.systems.inspect functionality offers everything we need here and we can just define patterns? But I think we should figure out what we want these checks to look like before migrating them across the tree. @alyssais Do you have any opinions on this?

Comment on lines 99 to 100
Copy link
Member

Choose a reason for hiding this comment

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

@reckenrode What do we want for Darwin here? I’m not sure what the balance of LLVM vs. cctools is currently.

Maybe it would be best to split this up into separate variables, but I’m not sure what the correct split would be.

Copy link
Contributor

Choose a reason for hiding this comment

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

Darwin’s bintools is almost all LLVM except for the following: ranlib, otool, install_name_tool, and ld. I’m currently testing a change to use ranlib from LLVM, so it might only be the last three for 25.11.

I’d really like to change the linker to ld64 to match what Darwin is actually using. Technically, cctools has another linker, but it’s old and not used anymore.

Copy link
Contributor

Choose a reason for hiding this comment

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

(In short, I think llvm is right for Darwin for bintools here.)

Comment on lines 105 to 111
Copy link
Member

Choose a reason for hiding this comment

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

We don’t use libcxxrt on any platform right now (but in the future it will probably make sense to use libc++ and libcxxrt on FreeBSD rather than the current libstdc++ plus libsupc++ stack). This should always be libsupc++ when using libstdc++.

Also, we should be consistent around cxx vs. c++ if we diverge from project names. I think I would favour using the upstream project names (so libstdc++, libc++abi, libcxxrt).

Copy link
Member Author

Choose a reason for hiding this comment

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

I've switched to replace ++ with xx. The idea behind using xx is then it's a bit nicer to interact with directly since you don't have to wrap in a string if it is an attribute name.

Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
"libunwind-darwin-host"
"libunwind-system"

“Host” is confusing wrt. hostPlatform. I think we don’t need to encode the Darwin detail because that can be conditioned on separately.

Copy link
Contributor

Choose a reason for hiding this comment

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

If we’re going to distinguish the system libunwind on Darwin, should we also distinguish using the system libc++ (once that lands)?

Copy link
Member Author

Choose a reason for hiding this comment

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

Renamed

Copy link
Member

Choose a reason for hiding this comment

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

I think this should just be libgcc. _s is for shared library.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

Comment on lines 84 to 101
Copy link
Member

Choose a reason for hiding this comment

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

I don’t think we should set these while they’re redundant to useLLVM (since they couldn’t be any other possible value, and adjusting them won’t work, and it means that e.g. lib.systems.examples.aarch64-freebsd // { useLLVM = false; } becomes broken for no good reason).

Copy link
Member Author

Choose a reason for hiding this comment

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

It's necessary for eval to work.

Copy link
Member Author

Choose a reason for hiding this comment

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

Since we have lib.systems.toolchain, we can use that to easily help clean out stdenv.hostPlatform of the toolchain attributes. Now that logic is handled outside of this file for setting the new toolchain attributes.

@RossComputerGuy
Copy link
Member Author

but it is possible we could do better and make this less error‐prone – e.g. expose something stdenv.hostPlatform.cxxlib == lib.toolchain.cxxlib.libcxx to compare against, or lib.toolchain.isLibcxx stdenv.hostPlatform.

100% agree on this

@alyssais
Copy link
Member

Maybe the existing lib.systems.inspect functionality offers everything we need here and we can just define patterns? But I think we should figure out what we want these checks to look like before migrating them across the tree. @alyssais Do you have any opinions on this?

Not especially, although reusing an existing mechanism sounds nice if it's workable.

@reckenrode
Copy link
Contributor

Maybe the existing lib.systems.inspect functionality offers everything we need here and we can just define patterns? But I think we should figure out what we want these checks to look like before migrating them across the tree. @alyssais Do you have any opinions on this?

If we’re going to distinguish the system libunwind and/or libc++ on Darwin, I would like to have some way to do these checks that treats them as libunwind and libc++ when you don’t care about that detail. Otherwise, everywhere that checks will have to condition on both variants, check a prefix, or be wrong for Darwin. (Obviously, there needs to be a way to distinguish when you do care, but I doubt that will be needed much outside of the LLVM derivation.)

@RossComputerGuy
Copy link
Member Author

If we’re going to distinguish the system libunwind and/or libc++ on Darwin, I would like to have some way to do these checks that treats them as libunwind and libc++ when you don’t care about that detail. Otherwise, everywhere that checks will have to condition on both variants, check a prefix, or be wrong for Darwin. (Obviously, there needs to be a way to distinguish when you do care, but I doubt that will be needed much outside of the LLVM derivation.)

Agreed, I think having a way to distinguish between a specific unwindlib (Apple's vs LLVM's) and a generic unwindlib (GCC vs LLVM) is definitely needed. I was thinking this could be done inside the specific derivations. We could have isAppleUnwind, isLLVM, and isGNU in the passthru.

@RossComputerGuy
Copy link
Member Author

Would be nice to continue on this.

@nixos-discourse
Copy link

This pull request has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/prs-ready-for-review/3032/6078

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

1.severity: significant Novel ideas, large API changes, notable refactorings, issues with RFC potential, etc. 6.topic: lib The Nixpkgs function library 8.has: documentation This PR adds or changes documentation 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.