Describe the bug
The following writeup assumes that autotools is our source of truth with regards to target triplets. This is the case in nixpkgs and also implicit for Nix use in general, since its configure system is autoconf-based and produces the system strings in the first place.
When fighting binutils' autoconf to accept Solo5's new and custom aarch64-solo5-none triplet, I noticed a curious discrepancy between nixpkgs' lib and autotools:
> nix-instantiate --eval -E 'with import <nixpkgs> {}; (lib.systems.elaborate "riscv64-none-elf").config'
"riscv64-unknown-none-elf"
> $(nix-build '<nixpkgs>' -A gnu-config)/config.sub riscv64-none-elf
riscv64-none-elf
> $(nix-build '<nixpkgs>' -A gnu-config)/config.sub riscv64-unknown-none-elf
Invalid configuration `riscv64-unknown-none-elf': Kernel `none' not known to work with OS `elf'.
The discrepancy can be boiled down to — after digging through the depths of config.sub for a bit — that autotools considers none a valid vendor, whereas for nixpkgs none can never be a vendor and will always be interpreted as a kernel.
When using lib.systems.examples, the problem is more subtle, since an explicit config argument is never elaborated:
> nix-instantiate --eval -E 'with import <nixpkgs> {}; (lib.systems.elaborate lib.systems.examples.riscv64-embedded).config' # correct
"riscv64-none-elf"
> nix-instantiate --eval -E 'with import <nixpkgs> {}; (lib.systems.elaborate lib.systems.examples.riscv64-embedded).parsed.vendor' # autotools believes this should be `none`
{ _type = "vendor"; name = "unknown"; }
So in conclusion, the following discrepancies between nixpkgs and autotools exists:
- nixpkgs considers
none only a valid kernel, whereas for autotools, it can both be a vendor and an OS
- nixpkgs considers
none-elf as a valid kernel-abi pairing; autotools does operate differently here:
- It uses Kernel-OS, so in
linux-musl and linux-gnu gnu and musl are considered OS, curiously.
- If instead of the Kernel-OS pairing it receives a single string, it'll consider that as the OS, whereas
nixpkgs would interpret it as the kernel always. This is somewhat important, since autotools prefixes
the OS with a modifier (the kernel) if it is given, whereas nixpkgs will postfix the kernel with a modifier
(the ABI). This is probably the biggest divergence I could make out philosophically, although in practice
I don't know of any cases where it produces problematic results.
The biggest problem I ran into was none-elf:
- nixpkgs thinks this is Kernel
none and ABI elf
- autotools won't accept this
elf is not an OS that works with Kernel none to their knowledge.
In the case of all example triplets, this problem is obscured by the fact that nixpkgs and autotools interpret the triplet differently, with autotools taking none for the vendor. When trying to force a certain vendor for aarch64-solo5-none, things fell apart:
aarch64-solo5-none would be accepted and parsed correctly by both, except that we would need to use aarch64-solo5-none-elf to make nixpkgs understand the exec format correctly
aarch64-solo5-none-elf will break autotools as described.
I think we were bound to run into some kind of problem at some point; The big problem with autotools is that (unless the triplet is in its most canonical form, i.e. of four components) you have to know what the possible values for each component are to expand the triplet correctly. Additionally, config.sub handles a couple of extra edge cases and backwards compatibility, resulting in a very intricate logic that's hard to replicate.
Another aspect is surely that we don't have a concept of multiple platform identifier systems, so all configs we use need to work with LLVM as well, since we have no concept of “convert this into an LLVM triple”. I need to research LLVM triples still, but possibly this could be a tamer system for us to use if we can figure out how to convert the triples to autotools target triplets correctly.
For the matter of the incorrect autotools triplets for the embedded platforms, I'm not sure how to proceed, actually. I think the first step would be to figure out where these triplets came from and what their correct autotools variant or interpretation would be:
riscv64-none-elf
riscv32-none-elf
aarch64-none-elf
aarch64_be-none-elf
arm-none-eabi{,hf}, powerpc{,le}-none-eabi (appear to be correct, i.e. autotools accepts arm-unknown-none-eabi which is the nixpkgs interpretation)
cc @alyssais @Ericson2314 @jaykru (added riscv* embedded) @matthewbauer @vincrusher (added embedded platforms)
Describe the bug
The following writeup assumes that autotools is our source of truth with regards to target triplets. This is the case in nixpkgs and also implicit for Nix use in general, since its configure system is autoconf-based and produces the
systemstrings in the first place.When fighting binutils' autoconf to accept Solo5's new and custom
aarch64-solo5-nonetriplet, I noticed a curious discrepancy between nixpkgs'liband autotools:The discrepancy can be boiled down to — after digging through the depths of
config.subfor a bit — that autotools considersnonea valid vendor, whereas for nixpkgsnonecan never be a vendor and will always be interpreted as a kernel.When using
lib.systems.examples, the problem is more subtle, since an explicitconfigargument is never elaborated:So in conclusion, the following discrepancies between nixpkgs and autotools exists:
noneonly a valid kernel, whereas for autotools, it can both be a vendor and an OSnone-elfas a valid kernel-abi pairing; autotools does operate differently here:linux-muslandlinux-gnugnuandmuslare considered OS, curiously.nixpkgs would interpret it as the kernel always. This is somewhat important, since autotools prefixes
the OS with a modifier (the kernel) if it is given, whereas nixpkgs will postfix the kernel with a modifier
(the ABI). This is probably the biggest divergence I could make out philosophically, although in practice
I don't know of any cases where it produces problematic results.
The biggest problem I ran into was
none-elf:noneand ABIelfelfis not an OS that works with Kernelnoneto their knowledge.In the case of all example triplets, this problem is obscured by the fact that nixpkgs and autotools interpret the triplet differently, with autotools taking
nonefor the vendor. When trying to force a certain vendor foraarch64-solo5-none, things fell apart:aarch64-solo5-nonewould be accepted and parsed correctly by both, except that we would need to useaarch64-solo5-none-elfto make nixpkgs understand the exec format correctlyaarch64-solo5-none-elfwill break autotools as described.I think we were bound to run into some kind of problem at some point; The big problem with autotools is that (unless the triplet is in its most canonical form, i.e. of four components) you have to know what the possible values for each component are to expand the triplet correctly. Additionally,
config.subhandles a couple of extra edge cases and backwards compatibility, resulting in a very intricate logic that's hard to replicate.Another aspect is surely that we don't have a concept of multiple platform identifier systems, so all
configs we use need to work with LLVM as well, since we have no concept of “convert this into an LLVM triple”. I need to research LLVM triples still, but possibly this could be a tamer system for us to use if we can figure out how to convert the triples to autotools target triplets correctly.For the matter of the incorrect autotools triplets for the embedded platforms, I'm not sure how to proceed, actually. I think the first step would be to figure out where these triplets came from and what their correct autotools variant or interpretation would be:
riscv64-none-elfriscv32-none-elfaarch64-none-elfaarch64_be-none-elfarm-none-eabi{,hf},powerpc{,le}-none-eabi(appear to be correct, i.e. autotools acceptsarm-unknown-none-eabiwhich is the nixpkgs interpretation)cc @alyssais @Ericson2314 @jaykru (added riscv* embedded) @matthewbauer @vincrusher (added embedded platforms)