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.
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.
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.
Cross-compilation of anything downstream of gtk3 requires qemu (due to
gobject-introspection) with --target-list=*-linux-user. Without this commit,
those qemu builds will fail on a powerpc64le host due to qemu being configured
with --cpu=powerpc64le instead of --cpu=ppc64le. Unfortunately the build
failure message from qemu in this situation is extremely cryptic.
The root cause turns out not to be the qemu expression, but rather the fact that
on powerpc64le hostPlatform.uname.processor returns the gnu-name (powerpc64le)
for the cpu instead of the linux-name (ppc64le) for the cpu.
uname.processor on mips64el also needs adjustment -- the Linux-name is "mips64"
for both big and little endian (unlike powerpc64, where the Linux-name includes
a "le" suffix):
```
nix@oak:/tmp$ uname -m; lscpu | head -n2
mips64
Architecture: mips64
Byte Order: Little Endian
```
uname.processor on powerpc32 has also been adjusted.
A tricky thing about FreeBSD is that there is no stable ABI across
versions. That means that putting in the version as part of the config
string is paramount.
We have a parsed represenation that separates name versus version to
accomplish this. We include FreeBSD versions 12 and 13 to demonstrate
how it works.
Move already implemented functionality to the upper level so
it could be used in a more generic way.
Signed-off-by: Ivan Nikolaenko <ivan.nikolaenko@unikie.com>
```
nix-repl> pkgsCross.arm-embedded.stdenv.hostPlatform.emulatorAvailable pkgsCross.arm-embedded.buildPackages
false
nix-repl> pkgsCross.aarch64-multiplatform.stdenv.hostPlatform.emulatorAvailable pkgsCross.aarch64-multiplatform.buildPackages
true
```
will be useful for stuff like handling https://github.com/NixOS/nixpkgs/issues/187109
The comment in lib/systems/default.nix for uname.processor indicates that it
should match `uname -p`. I tried that command and found that it reports
`unknown` on all of these machines:
- `x86_64-linux`
- `aarch64-linux`
- `mips64el-linux`
- `powerpc64le-linux`
The command `uname -m` reports the expected value on all of the above.
I think the comment is wrong. So I fixed it.
canExecute is like isCompatible, but also checks that the Kernels are
_equal_, i.e. that both platforms use the same syscall interface. This
is crucial in order to actually be able to execute binaries for the
other platform.
isCompatible is dropped, since it has changed semantically and there's
no use case left in nixpkgs.
Since the list only gates the platforms the nixpkgs flake exposes
packages to build on, the `hydra` label made little sense. It was also
only used for this purpose, so the `tier*` attributes were largely
unnecessary.
To reflect the intention more accurately, we expose
`lib.systems.flakeExposed` and use it to gate flake.nix's system list.
MIPS has a large space of {architecture,abi,endianness}; this commit
adds all of them to lib/systems/platforms.nix so we can be done with
it.
Currently lib/systems/inspect.nix has a single "isMips" predicate,
which is a bit ambiguous now that we will have both mips32 and mips64
support, with the latter having two ABIs. Let's add four new
predicates (isMips32, isMips64, isMips64n32, and isMips64n64) and
treat the now-ambiguous isMips as deprecated in favor of the
more-specific predicates. These predicates are used mainly for
enabling/disabling target-specific workarounds, and it is extremely
rare that a platform-specific workaround is needed, and both mips32
and mips64 need exactly the same workaround.
The separate predicates (isMips64n32 and isMips64n64) for ABI
distinctions are, unfortunately, useful. Boost's user-scheduled
threading (used by nix) does does not currently supports mips64n32,
which is a very desirable ABI on routers since they rarely have
more than 2**32 bytes of DRAM.
This will begin the process of breaking up the `useLLVM` monolith. That
is good in general, but I hope will be good for NetBSD and Darwin in
particular.
Co-authored-by: sterni <sternenseemann@systemli.org>