-
-
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
lib.systems: introduce toolchain, cc, and bintools attributes #365057
base: master
Are you sure you want to change the base?
lib.systems: introduce toolchain, cc, and bintools attributes #365057
Conversation
7a3eca0
to
2a005fa
Compare
9c8b44b
to
f6da63d
Compare
The main idea and motivation is in: pkgs/stdenv/cross/default.nix |
f6da63d
to
ec79349
Compare
10cd2ba
to
2b4d320
Compare
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/community-team-updates/56458/11 |
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 am not sure this approach is correct. useLLVM
is indeed a confusing mess that couples a bunch of things we probably don’t want to couple together, and that causes issues for Darwin. However, if we split it up – which I agree is a good idea – then what remaining meaning does toolchain
have? If it represents things like use of libunwind
, those should also be split up into their own fields. If, however, toolchain
is just a convenience to set all the other variables as #365057 (comment) suggests, then it’s definitely incorrect for packages to be conditioning on its value – as by definition, a different toolchain
value should have no meaning if all the other values are the same, and packages should instead condition on exactly what part of the platform they care about, which is the hard part of splitting up useLLVM
.
I have to agree, it seems to me that we are replacing an ad hoc system with a better, but still ad hoc system that, however, is more difficult to test. The What concerns me about the proposal presented here is that it doesn't achieve a clear separation between the parts it introduces:
I think another problem of our current approach with It doesn't make sense to remove such properties from the platform set necessarily because a) it's best that they are managed in a central place so expressions don't need to duplicate the logic and b) what may be computed for some platforms is configurable for others [citation needed] or may become configurable later [citation needed]. |
Right. What I’d like is that Though, really, once we do that, it seems that the utility of the
Actually, I believe the correct thing for Darwin today is LLVM |
Toolchain is covering more than just the cc, linker, and bintools. It's guarding previous checks for
I can update the predicates to add fixed attributes which change based on the new attributes. Then it'll be easier to check. But I think having better documentation on what
I'm not sure I follow with the behavior. Some of the new behavior is in place but to get any further would require significant work and likely would have to go to staging. My thinking was to leave that change for later, especially since a lot of packages and stuff will require tuning. |
That’s precisely the problem: we split things up, but don’t condition on the split things, so we still essentially have one monolithic coupled toolchain selector with the illusion of more specificity. “What toolchain? LLVM” is not an answer that makes sense if you can vary other components of the toolchain freely, and indeed this causes problems in practice now for Darwin. The only way to split it up that makes sense is to cover every bit of relevant variance as separate fields and ensure that all downstream packages look at those. |
The reason it's like that is because I was running into infinite recursions and cases where things weren't applying correctly. Darwin uses the |
But the Darwin toolchain is actually almost entirely LLVM except for the linker. Those issues are what would need fixing to make this a good step forward, rather than just adding additional variables that aren’t actually independent because of bugs in Nixpkgs. If we want to split up the toolchain fields then nothing downstream of |
Do we want this PR to have mass rebuilds on Darwin but none on Linux? Also, I'm not familiar with how Darwin does things so changing out |
5a22d29
to
a225595
Compare
Another note is we'll likely have to change |
I've got a log of the infinite recursion: https://gist.github.com/RossComputerGuy/d43df8fc4c3b6fe4adf8020db8c3a94a |
Again, there shouldn’t be any conditions on |
Then how do we get the same logic as |
The question is what they need to check it for. If it’s for the unwinding library, we should have a field for that too. If it’s about the C++ library, we should have a field for that too. If we continue to treat “LLVM toolchain” as a monolithic thing, then we won’t be able to vary these separate fields coherently, and we’ll continue to have issues with Darwin, so introducing these new attributes brings no real benefit. |
Ok, we'll probably need one for the C++ library, CC unwinder, and rtlib. Usually those are coupled with |
IIRC there’s already checks like |
That is null on the toplevel |
Ok, |
65bf933
to
09a9885
Compare
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’ll try to take a closer look at all the changed conditionals once we’ve settled on a design here; keeping my feedback to the lib
changes for now.
elaborate = systemOrArgs: | ||
assert lib.assertMsg (systemOrArgs ? useLLVM == false) "elaborate cannot contain the deprecated useLLVM attribute"; | ||
assert lib.assertMsg (systemOrArgs ? useArocc == false) "elaborate cannot contain the deprecated useArocc attribute"; | ||
assert lib.assertMsg (systemOrArgs ? useZig == false) "elaborate cannot contain the deprecated useZig attribute"; | ||
let |
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.
We might need a deprecation period for this.
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.
Probably 25.11 would be good to drop?
toolchain = | ||
/**/ if final.isDarwin then "apple" | ||
else if final.isFreeBSD || final.isOpenBSD then "llvm" | ||
else "gnu"; |
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.
Since we don’t have a clear separation between inputs and outputs for system elaboration (something that I agree we should fix in general), and since this should just be shorthand for setting a handful of other values in a platform definition – something that isn’t done very often at all – I think we should just drop toolchain
here, and specify cc
, bintools
, etc. manually. That will ensure that no code is conditioning on toolchain
and keep things factored out, at the cost of a bit of extra verbosity in the rare case of someone is defining a new platform.
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.
The problem I have with dropping toolchain
is then there's no easy way to get what the entire toolchain is. There's still cases where we cannot just check the C++ stdlib, CC, or the bintools.
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.
But I agree with #365057 (comment) that there is no such thing as “the entire toolchain”. The only way factoring out the components of what we currently gloss as a GCC toolchain or an LLVM toolchain or an Apple toolchain leads to a more consistent and flexible system is if we actually tease out the axes of difference. For instance, there is not really an “Apple” toolchain (at least not in Nixpkgs); Darwin uses a mostly LLVM toolchain with a few Apple components. You could want to build for Darwin using LLD (though that currently doesn’t work so well). You could want to build for Linux with Clang, libstdc++, and GNU binutils. Or for Linux with Clang, libc++, and mold.
So my answer to
There's still cases where we cannot just check the C++ stdlib, CC, or the bintools.
is that we have to enumerate those cases, figure out what the conditionals actually care about, and make sure those are represented orthogonally in the systems. If the fields are not orthogonal – if there’s a reason some of them must be tightly coupled – then we don’t gain anything by allowing them to vary independently.
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.
Look at cases where we have something like toolchain == "llvm"
in this PR. Some things like checks don't work under the toolchain but works with regular clang. It would be difficult and time consuming to go through and figure out which option specifically triggers the behavior. However, it would be the best option. Unfortunately, the full fine grain control just isn't there. Plus, having a toolchain
option makes it easier to specify what the set everything to like we had with using*
.
libcxx = | ||
/**/ if final.toolchain == "llvm" then "libcxx" | ||
else if final.toolchain == "gnu" then "libstdcxx" | ||
else null; |
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.
Are hostPlatform.libcxx == "libcxx"
and stdenv.cc.libcxx != null
ever going to disagree? If not, we can probably drop this? (Edit: Actually I guess we probably need it to decide whether we’re using libc++
in the first place.)
If we keep it, we should probably give it a name that doesn’t overlap with one of the options, to avoid confusion. There’s also the distinction of libc++abi
vs. libcxxrt
even when using libc++
(which is relevant for FreBSD; cc @rhelmot).
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.
Are
hostPlatform.libcxx == "libcxx"
andstdenv.cc.libcxx != null
ever going to disagree?
Yes.
nix-repl> legacyPackages.aarch64-linux.stdenv.cc.libcxx
null
nix-repl> legacyPackages.aarch64-linux.stdenv.hostPlatform.libcxx
"libstdcxx"
stdenv.cc.libcxx
doesn't look like a reliable way to get the C++ stdlib.
If we keep it, we should probably give it a name that doesn’t overlap with one of the options, to avoid confusion. There’s also the distinction of
libc++abi
vs.libcxxrt
even when usinglibc++
.
So what would be a better name? cxx-std
?
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’m not too fussed about the name; cxxlib
seems consistent with the other choices in this PR. (That result seems consistent to me, though? aarch64-linux
doesn’t use libc++
, so stdenv.cc.libcxx
is null
.)
Things done
Replaces
useLLVM
,useArocc
, anduseZig
withtoolchain
,cc
,linker
, andbintools
attributes. This might not produce any rebuilds but we'll see. This has the advantage of preventingusing${compiler}
flags from colliding and not working correctly if we were to stack multiplepkgs*
together.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.