Add `.chezmoi.rustArchTriple` template variable
twpayne opened this issue · comments
Is your feature request related to a problem? Please describe.
I'm always frustrated when I want to download platform-specific binaries built with Rust and have to construct the binary's URL myself.
Typically this includes a Rust architecture string, which requires a lot of template gymnastics, especially because chezmoi's Go-based view of operating systems (runtime.GOOS
) and architectures (runtime.GOARCH
) do not map well onto Rust's supported operating systems and architectures.
Describe the solution you'd like
As @halostatue said, it would be great if chezmoi had a .chezmoi.rustArchTriple
template variable that people could use in their templates.
Describe alternatives you've considered
Constructing Rust arch triples in my own configs.
Additional context
Refs #3735 for .deb
and .rpm
support.
cc @VorpalBlade as a Rust expert
This might be better as a template function because there are some variations which may require some special handling. Linux has the choice between musl and glibc and Windows has the choice between msvc and mingw (glibc) and mingw (llvm).
Maybe something like rustArchTarget [optional-library-value]
. For platforms that don’t have choices, the argument(s) are ignored. For those that do have choices, the default would either be (a) default for GOOS
and GOARCH
combinations and/or (b) (if possible) overridden for specific builds (e.g., apk/alpine).
I’ve always seen it called the triple
, but given that some of them are 4+. parts long, maybe just rustArch
or rustArchTarget
or rustTarget
.
There’s four classes of architectures for Rust:
- Tier 1
- Tier 2 (hosted)
- Tier 2 (not hosted)
- Tier 3 (ad hoc, community supported)
Chezmoi only supports a subset of the possible Rust architectures even for the first three.
Tier 1
aarch64-unknown-linux-gnu
:linux_arm64
(except probablyapk
) glibci686-pc-windows-msvc
: probablywindows_i386
; 32-bit Windows MSVCi686-pc-windows-gnu
:windows_i386
; 32-bit Windows MinGWi686-unknown-linux-gnu
:linux_i386
(except probablyapk
) 32-bit glibcx86_64-apple-darwin
:darwin-amd64
x86_64-pc-windows-gnu
: maybewindows_amd64
x86_64-pc-windows-msvc
: probablywindows_amd64
x86_64-unknown-linux-gnu
:linux_amd64
(except probablyapk
) glibc
Tier 2 (Hosted)
aarch64-apple-darwin
:darwin-arm64
aarch-pc-windows-msvc
:windows_arm64
aarch64-unknown-linux-musl
:linux_arm64.apk
loongarch64-unknown-linux-gnu
:loong64
exceptapk
glibcpowerpc64-unknown-linux-gnu
:ppc64
exceptapk
glibcpowerpc64le-unknown-linux-gnu
:ppc64le
exceptapk
glibcriscv64gc-unknown-linux-gnu
:riscv64
exceptapk
glibcs390x-unknown-linux-gnu
:s390x
exceptapk
glibcx86_64-unknown-freebsd
:freebsd_amd64
x86_64-unknown-linux-musl
:linux-amd64-musl
Tier 2 (Not Hosted)
aarch64-linux-android
:android_arm64
arm-unknown-linux-musleabi
:linux_arm
i686-unknown-freebsd
:freebsd_i386
i686-unknown-linux-musl
:linux_i386
apk
Tier 3
arm64ec-pc-windows-msvc
:windows_arm
maybe?aarch64-unknown-freebsd
:freebsd_arm64
aarch64-unknown-openbsd
:openbsd_arm64
armv6-unknown-freebsd
:freebsd_arm
maybe? (might bearmv7-unknown-freebsd
)i686-unknown-openbsd
:openbsd_i386
loongarch64-unknown-linux-musl
loong64
apkmips64-unknown-linux-gnuabi64
:mips64
probablymips64el-unknown-linux-gnuabi64
:mips64le
probablypowerpc64-unknown-linux-musl
:ppc64
apkpowerpc64le-unknown-linux-musl
:ppc64le
apkriscv64gc-unknown-linux-musl
:risc
apks390x-unknown-linux-musl
:s390x
apkx86_64-unknown-openbsd
:openbsd_amd64
chezmoi
with No Matching Triple
armhfp.rpm
mips64le_hardfloat
linux_armel
openbsd_arm
This leaves a number of unsupported or not-clearly-supported Tier 2 targets which might work because Go doesn’t actually use libc
unless CGO is used.
Tier 2 Hosted
arm-unknown-linux-gnueabi
: ARMv6 Linux (kernel 3.2, glibc 2.17)arm-unknown-linux-gnueabihf
: ARMv6 Linux, hardfloat (kernel 3.2, glibc 2.17)armv7-unknown-linux-gnueabihf
: ARMv7-A Linux, hardfloat (kernel 3.2, glibc 2.17)powerpc-unknown-linux-gnu
: PowerPC Linux (kernel 3.2, glibc 2.17)x86_64-unknown-illumos
: illumosx86_64-unknown-netbsd
: NetBSD/amd64
Tier 2 Not Hosted
aarch64-apple-ios
: ARM64 iOSaarch64-apple-ios-sim
: Apple iOS Simulator on ARM64aarch64-fuchsia
: Alias for aarch64-unknown-fuchsiaaarch64-unknown-fuchsia
: ARM64 Fuchsiaaarch64-pc-windows-gnullvm
: ARM64 MinGW (Windows 10+), LLVM ABIaarch64-unknown-linux-ohos
: ARM64 OpenHarmonyarm-linux-androideabi
: ARMv6 Androidarm-unknown-linux-musleabihf
: ARMv6 Linux with musl 1.2.3, hardfloatarmv5te-unknown-linux-gnueabi
: ARMv5TE Linux (kernel 4.4, glibc 2.23)armv5te-unknown-linux-musleabi
: ARMv5TE Linux with musl 1.2.3armv7-linux-androideabi
: ARMv7-A Androidarmv7-unknown-linux-gnueabi
: ARMv7-A Linux (kernel 4.15, glibc 2.27)armv7-unknown-linux-musleabi
: ARMv7-A Linux with musl 1.2.3armv7-unknown-linux-musleabihf
: ARMv7-A Linux with musl 1.2.3, hardfloatarmv7-unknown-linux-ohos
: ARMv7-A OpenHarmonyi586-unknown-linux-gnu
: 32-bit Linux w/o SSE (kernel 3.2, glibc 2.17) 2i586-unknown-linux-musl
: 32-bit Linux w/o SSE, musl 1.2.3 2i686-linux-android
: 32-bit x86 Android 1i686-pc-windows-gnullvm
: 32-bit x86 MinGW (Windows 10+), LLVM ABI 1sparc64-unknown-linux-gnu
: SPARC Linux (kernel 4.4, glibc 2.23)sparcv9-sun-solaris
: SPARC Solaris 11, illumosthumbv7neon-linux-androideabi
: Thumb2-mode ARMv7-A Android with NEONthumbv7neon-unknown-linux-gnueabihf
: Thumb2-mode ARMv7-A Linux with NEON (kernel 4.4, glibc 2.23)wasm32-unknown-emscripten
: WebAssembly via Emscriptenwasm32-unknown-unknown
: WebAssemblywasm32-wasi
: WebAssembly with WASI (undergoing a rename to wasm32-wasip1)wasm32-wasip1
: WebAssembly with WASIwasm32-wasip1-threads
:x86_64-apple-ios
: 64-bit x86 iOSx86_64-fortanix-unknown-sgx
: Fortanix ABI for 64-bit Intel SGXx86_64-fuchsia
: Alias for x86_64-unknown-fuchsiax86_64-unknown-fuchsia
: 64-bit x86 Fuchsiax86_64-linux-android
: 64-bit x86 Androidx86_64-pc-solaris
: 64-bit Solaris 11, illumosx86_64-pc-windows-gnullvm
: 64-bit x86 MinGW (Windows 10+), LLVM ABIx86_64-unknown-linux-gnux32
: 64-bit Linux (x32 ABI) (kernel 4.15, glibc 2.27)x86_64-unknown-linux-ohos
: x86_64 OpenHarmonyx86_64-unknown-redox
: Redox OS
This list is based on Rust Platform Support and the latest release of chezmoi to see the pre-built versions.
This leaves a number of unsupported or not-clearly-supported Tier 2 targets which might work because Go doesn’t actually use libc unless CGO is used.
I can confirm that I used to use chezmoi and rust on a 32-bit Raspberry Pi. Which I believe was "armv7-unknown-linux-gnueabihf
: ARMv7-A Linux, hardfloat (kernel 3.2, glibc 2.17)".
Arm is a bit of a rabbit hole of strange target triplets with hard float vs software float. MIPS has this too (but is becoming less and less relevant). That is not a rust specific problem, I believe you see these over in C/C++-land too. That said, I'm not sure if there are any additional quirks of rust target strings vs GCC / LLVM ones.
Also, musl targets are a bit strange in rust. These are normally statically linked, such that the resulting binary can run anywhere. This can be useful to deal with the mess that is glibc backward compatibility: if you build against a newer glibc it can't run on an older one.
However, you can build dynamically against musl too, and on alpine I believe that is the default.
Windows is another strange case, with two different targets: msvc or gnu (mingw). I'm not an expert on Windows at all, but as I understand it these two toolchains are not compatible (ABI differs, different libc, etc).
In both these cases it means that there could be two different target triplets that might work for your platform. And if your goal is to figure out whst pre-build binary to download from github releases, you would have to check both in case only one of them is provided. For example I only provide static musl builds for paketkoll because of the pain that is glibc backward compatibility. But these will run on a -gnu
host too.
Also: Mac might or might not have universal binaries I believe. And Rosetta. But I know nothing about how that works, I haven't owned a mac since the 90s.
macOS has universal binaries, but I do not believe that Rust tools are typically built universal (I don’t think that rustc
or crate
can do this natively, so there would be some otool
or similar shenanigans that would have to happen).
What I was thinking with a rustArch
template function is something like this:
- macOS:
rustArch [arm64|amd64]
- by default returns the native arch, but can be overridden to the other as appropriate. - Windows:
rustArch [mscv|mingw] [arm64|amd64|i686]
- by default returns the native arch for MSCV, but can be overridden for MinGW and/or arm/x86-64/x86-32 as appropriate. - Linux:
rustArch [glibc|musl] [arch?]
- by default returns the native arch glibc (or musl, maybe) but can be overridden as appropriate. On Alpine (and/or other known musl targets) the default return is musl, not glibc.
We could have a .chezmoi.rustArch
that boils down to the default value returned from rustArch
, but that doesn’t really allow for alternatives.
Thank you for the deep technical discussion!
Given #3735 (comment), I'll close this issue.