Skip to content

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

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

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

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
@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.

@nixpkgs-ci nixpkgs-ci bot added the 12.approvals: 2 This PR was reviewed and approved by two persons. label Jun 25, 2025
@Qyriad Qyriad added the 1.severity: significant Novel ideas, large API changes, notable refactorings, issues with RFC potential, etc. label Jun 25, 2025
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
bintools =
if final.useLLVM || final.useArocc || final.useZig || final.isDarwin then "llvm" else "gnu";
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
cxxrtlib =
if final.useLLVM || final.useArocc || final.useZig || final.isDarwin then
"libcxxabi"
else if final.isLinux then
"libsupc++"
else
"libcxxrt";
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.

if final.useLLVM || final.useArocc || final.useZig then
"libunwind"
else if final.isDarwin then
"libunwind-darwin-host"
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

else if final.isDarwin then
"libunwind-darwin-host"
else
"libgcc_s";
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
useLLVM = true;
cc = "clang";
bintools = "llvm";
cxxlib = "libcxx";
cxxrtlib = "libcxxabi";
unwindlib = "libunwind";
rtlib = "compiler-rt";
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.

@nix-owners nix-owners bot requested a review from Artturin July 3, 2025 21:18
@nixpkgs-ci nixpkgs-ci bot added the 2.status: merge conflict This PR has merge conflicts with the target branch label Jul 26, 2025
@nixpkgs-ci nixpkgs-ci bot removed the 2.status: merge conflict This PR has merge conflicts with the target branch label Aug 15, 2025
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.