ziglang / zig

General-purpose programming language and toolchain for maintaining robust, optimal, and reusable software.
https://ziglang.org
MIT License
35.02k stars 2.56k forks source link

support detecting the native CPU architecture as being different than the current target #4592

Open andrewrk opened 4 years ago

andrewrk commented 4 years ago

On my PineBook I can observe the following situation:

env: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, BuildID[sha1]=736db6308048687a73c5fad96fb7779a41e3b213, stripped

That's a a 32-bit ARM ELF file, with a 32-bit dynamic linker path. There is no 64-bit dynamic linker in /lib, only the 32-bit one.

zig builtin reports aarch64 for the CPU architecture since that matches the zig binary downloaded from ziglang.org. It was looking for an aarch64 dynamic linker path when looking at /usr/bin/env and so it did not find one, and reports the default C ABI of musl, which is incorrect for this Debian installation, and the default 64-bit dynamic linker path for aarch64, which is incorrect. It also fails to detect the system glibc version, for reasons related to how the /usr/bin/env ELF file is parsed (runpaths are stored a different way).

This issue is to make native target detection even more powerful, in that it can choose the native CPU architecture. In this case it would be detecting 32-bit arm even though the zig compiler itself is an aarch64 binary.

I believe a similar situation is possible with x86_64 and i386. (64-bit CPU; 32-bit OS installation)

It may make sense to do this after #4591 is complete.

mikdusan commented 3 years ago

here's a command that might make a good discriminator:

/usr/bin/getconf LONG_BIT

on my x86_64 mac:


os current native detect map ? LONG_BIT != native.bit readelf(1)
debian-i386 i386-linux-gnu
debian-i386 x86_64-linux-gnu i386-linux-gnu ELF32
debian-x86_64 x86_64-linux-gnu ELF64
debian-armhf arm-linux-gnu
debian-armhf aarch64-linux-gnu arm-linux-gnu
debian-arm64 aarch64-linux-gnu
archlinux x86_64-linux-gnu ELF64
alpinelinux-x86_64 ELF64
openbsd-x86_64 missing LONG_BIT ELF64
  1. `readelf -h /usr/bin/env | grep Class | awk '{ print $2 }'
andrewrk commented 3 years ago

Thanks for doing this research. Can I ask for one more column in the table? readelf -h /usr/bin/env | grep Class

I think the existence of /usr/bin/env is more universal than getconf.

mikdusan commented 3 years ago
semarie commented 3 years ago

getconf is a posix tool to query configuration variables, so it should be as portable as env. it should be also possible to directly query variables via C interface: sysconf().

but please note that LONG_BIT configuration variable isn't defined in posix, and so this name isn't portable (and doesn't exist on OpenBSD for example)

semarie commented 3 years ago

doesn't exist on OpenBSD for example

just as I was trying the command your comment came in. I have a openbsd 6.6 vm nothing special and LONG_BIT is there. and readelf is there and works the same way giving me ELF64 result.

it was working in 6.6 ? in 6.9-beta it doesn't... it would be something to investigate.

$ sysctl kern.version
kern.version=OpenBSD 6.9-beta (GENERIC.MP) #371: Tue Mar  2 10:42:59 MST 2021
    deraadt@amd64.openbsd.org:/usr/src/sys/arch/amd64/compile/GENERIC.MP

$ getconf LONG_BIT
getconf: LONG_BIT: unknown variable

regarding readelf, yes it is present in base system (in compXX set, so some users could have it not installed, even if not a recommanded configuration)

mikdusan commented 3 years ago

@semarie sorry I wrote that too fast - was running commands in the wrong terminal window. You're correct, OpenBSD does not have LONG_BIT.

waruqi commented 2 years ago

We can use uname -m to detect arch on OpenBSD.

$ uname -m
amd64

and it is also support for linux and macOS.