An important idea around the rust stuff in lib.systems is that it's
elaborated — this means that it should idempotently add to the values
passed in, if any. But we missed that the names used for the
parameter and the elaborated value for "rustcTarget"/"config" didn't
line up. The intention was to use "rustcTarget" everywhere in the new
interface, as a more descriptive name than "config".
This fixes setting the system in NixOS configuration, which results in
an already elaborated system being elaborated again. Before, this
wouldn't produce the correct result:
% nix-instantiate --eval -A stdenv.hostPlatform.rust.rustcTarget --system armv7l-linux
"armv7-unknown-linux-gnueabihf"
% NIX_PATH= nix-instantiate --eval -E '(import nixos/lib/eval-config.nix { system = "armv7l-linux"; modules = []; }).pkgs.stdenv.hostPlatform.rust.rustcTarget'
"arm-unknown-linux-gnueabihf"
Fixes: e3e57b8f18 ("lib.systems: elaborate Rust metadata")
Fixes: https://github.com/NixOS/nixpkgs/issues/271000
Usually, attributes passed explicitly to elaborate take precedence
over the elaborated ones, but since we also elaborate the nested
"rust" attrset, we need to push that one level down, so the rest of
"rust" is still filled in if you just pass
{ rust = { config = ... } }.
I've had to drop the assertion that checked that at most one of "rust"
and "rustc" was part of the un-elaborated system, because doing this
broke passing an elaborated system in, which should be idempotent.
For the same reason, I've also had to make it possible for
rust.rustcTargetSpec to be passed in. Otherwise, on the second call,
since platform was filled in by the first, the custom target file
would be constructed. The only other way to avoid this would be to
compare the platform attrs to all built in Rust targets to check it
wasn't one of those, and that isn't feasible.
Fixes: e3e57b8f18 ("lib.systems: elaborate Rust metadata")
We need this stuff to be available in lib so make-derivation.nix can
access it to construct the Meson cross file.
This has a couple of other advantages:
- It makes Rust less special. Now figuring out what Rust calls a
platform is the same as figuring out what Linux or QEMU call it.
- We can unify the schema used to define Rust targets, and the schema
used to access those values later. Just like you can set "config"
or "system" in a platform definition, and then access those same
keys on the elaborated platform, you can now set "rustcTarget" in
your crossSystem, and then access "stdenv.hostPlatform.rustcTarget"
in your code.
"rustcTarget", "rustcTargetSpec", "cargoShortTarget", and
"cargoEnvVarTarget" have the "rustc" and "cargo" prefixes because
these are not exposed to code by the compiler, and are not
standardized. The arch/os/etc. variables are all named to match the
forms in the Rust target spec JSON.
The new rust.target-family only takes a list, since we don't need to
worry about backwards compatibility when that name is used.
The old APIs are all still functional with no warning for now, so that
it's possible for external code to use a single API on both 23.05 and
23.11. We can introduce the warnings once 23.05 is EOL, and make them
hard errors when 23.11 is EOL.
We have several cross-compilation bugs that show up if
hostPlatform!=buildPlatform yet
hostPlatform.config==buildPlatform.config.
These bugs have appeared and disappeared as we've fiddled with the
definition of equality for platform objects. This commit adds a
clear-cut case where they are *not* equal and never will be, so we
can test it.
gnu-config will ignore the portion of a triple matching the regex
`e?abi.*$` when determining the validity of a triple. In other
words, `i386-linuxabichickenlips` is a valid triple.
This commit updates our parsing routines to match gnu-config.
I was recently surprised to discover that it is in fact possible to
shoehorn ABI flavors into nix doubles in a way which preserves their
property of being a (non-canonical) subset of the valid gnu-config
triples. This commit is required in order to exploit that discovery
to add automatic detection of ILP32 platforms (64-bit void*, 32-bit
int, like the Apple Watch and MIPS n32) to Nix.
The Minimalist Gnu for Windows distribution comes with support for
the traditional msvcrt libc, as well as ucrt64 libc. The latter
being the newer universal compiler runtime. We follow the msys2
environment naming convention[1]:
| name | toolchain | arch | libc | libc++ |
|------------|-----------|---------|--------|-----------|
| mingw32 | gcc | i686 | msvcrt | libstdc++ |
| mingw64 | gcc | x86_64 | msvcrt | libstdc++ |
| ucrt64 | gcc | x86_64 | ucrt | libstdc++ |
| clang32 | llvm | i686 | ucrt | libc++ |
| clang64 | llvm | x86_64 | ucrt | libc++ |
| clangarm64 | llvm | aarch64 | ucrt | libc++ |
For now nixpkgs only supports the first three with this commit.
--
[1]: https://www.msys2.org/docs/environments/
Add support for Nvidia's Bluefield 2 plattform as a compilation
target. There exists a version with and without crypto support,
while the crypto supported version is the most common one.
Support for the non-crypto version can be easily added in the future,
if needed.
For a datasheet of the hardware, see:
https://www.nvidia.com/content/dam/en-zz/Solutions/Data-Center/documents/datasheet-nvidia-bluefield-2-dpu.pdf
Signed-off-by: Markus Theil <theil.markus@gmail.com>
Because downstream code expects to use `==` on platform attrsets, we
are unfortunately not able to throw a useful error message when the
`sharedLibrary` attribute is accessed.
When users do a comparison like:
stdenv.hostPlatform == pkgsStatic.stdenv.hostPlatform
... in a situation where `stdenv.hostPlatform.hasSharedLibraries`,
they expect this to return `false`. Unfortunately Nix does a deep
equality comparison here, and ends up forcing the
`pkgsStatic.stdenv.hostPlatform.extensions.sharedLibrary` attribute,
which throws the error.
Rather than returning `null`, this commit instead simply omits the
`extensions.sharedLibrary` attribute. This provides the user with a
more-useful error message: instead of waiting until the `null` is
used (and hoping that produces an error), the user will get an error
about the `extensions.sharedLibrary` attribute being missing, at the
position where it was referenced.
Big thanks to @trofi for his PR to add
`NIX_VALIDATE_EVAL_NONDETERMINISM` to Nix, which I am now using. It
made tracking this down really easy!
Fixes#244045
This commit adds `hasSharedLibraries` to `lib.systems`.
We need `plat.hasSharedLibraries` in order to know whether or not to
expect `gcc` (and many other tools) to emit shared libraries (like
`libgcc_s.so`). Many of the GNU build scripts are smart enough that
if you configure them with `--enable-shared` on a platform (such as
`arm-none-eabi`) that doesn't support dynamic linking, they will
simply skip the shared libraries instead of aborting the
`configurePhase`. Unfortunately the missing shared libraries in the
final build product cause very hard-to-troubleshoot problems later
on.
The alternative to introducing `hasSharedLibraries` would be to set
`isStatic` in these situations. However doing so causes
`make-derivation.nix` to insert `-static` between the `pname` and
`hostPlatform` suffix, which is undesirable.
If at some point in the future we eliminate the `-static` suffix,
then `hasSharedLibraries` can be made equal to `!isStatic`.
toLosslessStringMaybe is not used by anything other than lib/tests,
so it can be private to that file.
I don't think this function was terribly well thought-through. If
people start using it, we will become permanently dependent on the
ability to test platforms for equality. It also makes the
elaboration process more fragile, because it encourages code outside
of nixpkgs to become sensitive to the minute details of how
elaboration happens.
The eminent Donald E. Knuth should be recognized as having equal
standing with such entities as IBM, Apple, and the Personal
Computer. We should acknowledge this by including him as a "vendor".
Also, `gnu-config` recognizes `mmix-knuth-*` triples (and in fact
requires `vendor="knuth"` when `cpu="mmix"`) -- so we sort of have
to. But we should do it anyways.
We already have examples for these, but since we didn't actually
recognise the doubles, it wasn't possible to build any packages for
them without setting allowUnsupportedSystem.
I imagine this was supposed to be rustc = args.rustc, like the other
two lines. This meant that we accepted both rust and rustc
attributes, with the same effect. I doubt anybody was using the
undocumented, probably-accidental "rust" spelling, but we should
remove it before somebody starts.
In fact, we don't need to set rustc here at all, because no value
platforms.select could return will ever include a rustc key (unlike
the other two), so then rustc will be filled in later, when args is
merged into final.
It makes sense to allow platform definitions to opt out of having libc
at all. One use case would be targetting some obscure new Linux
target that doesn't have a libc implementation yet, and another is
UEFI, which is basically libc-less Windows.
Not having libc is not commonly specified in (GNU) triples (even
Linux's build system will just target either -gnu or -musl depending
on the platform), so instead, we use a separate attribute for it.