Closed abdullah2993 closed 1 year ago
@abdullah2993 This seems like a good feature to add. Probably in the form of an arch()
function that returns a String
corresponding to the architecture, in rustup's architecture format, rather than from the system's API:
aarch64
arm
armebv7r
armv5te
armv7
armv7a
armv7r
asmjs
i586
i686
mips
mips64
mips64el
nvptx64
powerpc
powerpc64
powerpc64le
riscv32i
riscv32imac
riscv32imc
riscv64gc
riscv64imac
s390x
sparc64
sparcv9
thumbv6m
thumbv7em
thumbv7m
thumbv7neon
thumbv8m
wasm32
x86_64
Either that, or create a non exhaustive enum of all the possible architectures, which might be better because then it can implement a method to get the number of bits for the architecture.
Friendly ping @AldaronLau.
I would like to give this a try, any tips on how to implement this?
We can get those constants through std::env::consts::ARCH at compile time, but it is flawed. Since this information is generated at compile time, if we have a binary built for platform A, then we run it on platform B (e.g., a binary for x86 can be run on x86-64 platforms), then the result would simply be wrong.
@SteveLauC Thanks for your interest! It will have to be implemented separately for each platform calling into system APIs.
A simple solution for Linux would be to execute the lscpu
command and parse the first line of output (which I believe is transformed from the data in /proc/cpuinfo
, although I'm not quite sure how - which whoami could do itself instead of relying on the external command):
Architecture: x86_64
On WebAssembly, this information would not be exposed, so it's ok to use compile time checks to get the "architecture".
MacOS, BSD and Windows will need their own separate implementations calling into the respective system APIs (requires some research).
Researching and implementing this feature isn't high priority on my todo list, so help would be greatly appreciated! Also, since there are multiple platforms, I wouldn't expect them to be all done in one PR (feel free to break it up if you decide to implement it).
As for the exposed API, I'm thinking something along the lines of:
pub enum Arch {
/// aarch64
Aarch64,
/// i686
I686,
/// x86_64
X86,
// Etc.
}
pub enum PointerSize {
Bits32,
Bits64,
}
impl Arch {
pub fn bits() -> PointerSize {
todo!()
}
}
pub fn arch() -> Arch {
// Default for unsupported platforms would fallback to converting from `std::env::consts::ARCH`
}
I think either way for Linux (the lscpu
command or parsing /proc/cpuinfo
) would be fine initially, although I would like to move the whoami crate away from depending on external commands.
So we are going to implement this feature using the following approach:
lscpu(1)
| /proc/cpuinfo
(runtime)std::env::consts::ARCH
(compile time)Windows: GetNativeSystemInfo
(runtime)
Any reason why not to call uname(2)
on those UNIX (including Linux) platforms? The implementation would be something like this:
I know
whoami
does not rely on external crate likelibc
ornix
, it's fine, we can link to libc ourselves.
use nix::sys::utsname::uname;
fn main() {
let res = uname().unwrap();
println!("{:?}", res.machine());
}
One concern about uname(2)
is that I didn't find the full list of architecture strings that could be returned from it. I looked at these two answers this morning:
include/generated/compile.h
compile.h
is generated from scripts/mkcompile_h
Then I take a look at the contents of mkcompile_h
, finding that that arch string is the first command line argument passed to this script:
UTS_MACHINE=$1
Then I was lost because I have no idea how the kernel is built (i.e., how those build scripts are executed, in which order).
Perhaps I should take a look at the POSIX standard to find out if they have any specifications on this returned arch string.
Any reason why not to call
uname(2)
on those UNIX (including Linux) platforms? The implementation would be something like this:
That's a better solution than the one I suggested, uname()
is the way to go.
I know
whoami
does not rely on external crate likelibc
ornix
, it's fine, we can link to libc ourselves.use nix::sys::utsname::uname; fn main() { let res = uname().unwrap(); println!("{:?}", res.machine()); }
Yeah, it will have to include the extern "C"
definition manually.
Perhaps I should take a look at the POSIX standard to find out if they have any specifications on this returned arch string.
That sounds like a good plan.
Is your feature request related to a problem? Please describe. No. It would be a nice to have feature.
Describe the solution you'd like Ability to get the arch of the OS.
Describe alternatives you've considered There is a crate available for that https://crates.io/crates/bitness crate
Additional context Although there are crates available that does the same thing but it would be nice to have it included in
whoami