Is it possible to programmatically determine, at run time, if an App is running on Apple Silicon? If so, how?
Programmatically detect Apple Silicon (i.e. ARM CPU)
https://developer.apple.com/documentation/apple_silicon/about_the_rosetta_translation_environment
int processIsTranslated() {
int ret = 0;
sizet size = sizeof(ret);
if (sysctlbyname("sysctl.proctranslated", &ret, &size, NULL, 0) == -1)
{
if (errno == ENOENT)
return 0;
return -1;
}
return ret;
}
int processIsTranslated() {
int ret = 0;
sizet size = sizeof(ret);
if (sysctlbyname("sysctl.proctranslated", &ret, &size, NULL, 0) == -1)
{
if (errno == ENOENT)
return 0;
return -1;
}
return ret;
}
my 2 cents for swift:
```
Code Block // swift implementation of ADC call let NATIVE_EXECUTION = Int32(0) let EMULATED_EXECUTION = Int32(1) let UNKONWN_EXECUTION = -Int32(1) func processIsTranslated() ->Int32 { var ret = Int32(0) var size = ret.byteWidth let result = sysctlbyname("sysctl.proc_translated", &ret, &size, nil, 0) if result == -1 { if (errno == ENOENT){ return 0 } return -1 } return ret } func processIsTranslatedStr() -> String { switch processIsTranslated() { case NATIVE_EXECUTION: return "native" case EMULATED_EXECUTION: return "rosetta" default: return "unkown" } }
```
Found it.. well for the iOS app case anyway: https://developer.apple.com/documentation/foundation/processinfo/3608556-isiosapponmac
The "sysctl.proc_translated" suggestions are only going to tell you if the an Intel (x86_64) binary is running via Rosetta 2 on an Apple Silicon based Mac.
If you want to check the architecture at runtime, you can use uname(_:) to do just that. I added an extension to ProcessInfo to provide a bit more of a modern API for it:
On an Apple Silicon based mac, this will return arm64 whereas on an Intel one it'll be x86_64. Be aware however that if your program is running in Rosetta then it'll return x86_64 again... You could combine it with the other solutions to check that it's also not running as translated to overcome that edge case.
If you want to check the architecture at runtime, you can use uname(_:) to do just that. I added an extension to ProcessInfo to provide a bit more of a modern API for it:
Code Block swift extension ProcessInfo { /// Returns a `String` representing the machine hardware name or nil if there was an error invoking `uname(_:)` or decoding the response. /// /// Return value is the equivalent to running `$ uname -m` in shell. var machineHardwareName: String? { var sysinfo = utsname() let result = uname(&sysinfo) guard result == EXIT_SUCCESS else { return nil } let data = Data(bytes: &sysinfo.machine, count: Int(_SYS_NAMELEN)) guard let identifier = String(bytes: data, encoding: .ascii) else { return nil } return identifier.trimmingCharacters(in: .controlCharacters) } }
On an Apple Silicon based mac, this will return arm64 whereas on an Intel one it'll be x86_64. Be aware however that if your program is running in Rosetta then it'll return x86_64 again... You could combine it with the other solutions to check that it's also not running as translated to overcome that edge case.
Since I needed to detect this stuff for a project, I made a Swift package that includes your solutions and improves upon them and makes them easier to use.
It can also detect multiple architectures to have a more general usage.
https://github.com/ITzTravelInTime/SwiftCPUDetect
Here is some example usage of my package
import Foundation
import SwiftCPUDetect
print("Is my app running with Rosetta? \((AppExecutionMode.current() == .emulated) ? "Yes" : "No")")
print("My app is running using the \(CpuArchitecture.current()?.rawValue ?? "[Can't detect architecture]") architecture")
print("My computer is running using the \(CpuArchitecture.actualCurrent()?.rawValue ?? "[Can't detect architecture]") architecture")