Is there something I can type on the command-line to determine if an executable is an ARM/M1 or an x86 binary?
-
2Related https://apple.stackexchange.com/questions/408596/how-to-tell-if-dmg-file-contains-universal-binaries-i-e-if-it-has-been-compile – nohillside Oct 20 '21 at 09:57
-
1Pay attention that on MacOS (with its "Universal Binary" architecture) It isn't an M1 binary OR x86 binary, but And/Or -- and there are more supported architectures too. – Motti Shneor Oct 27 '21 at 09:43
4 Answers
You can use the file command to see which architectures a binary (or library) includes native code for. The M1 processor uses the 64-bit ARM architecture, so it'll be listed as "arm64". I don't have an M1 Mac or any ARM-only binaries handy, but compare the Chrome (Intel-only) and Firefox ("universal"/"fat" binary supporting both Intel and ARM) on my Mac:
$ file /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome
/Applications/Google Chrome.app/Contents/MacOS/Google Chrome: Mach-O 64-bit executable x86_64
$ file /Applications/Firefox.app/Contents/MacOS/firefox
/Applications/Firefox.app/Contents/MacOS/firefox: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64] [arm64:Mach-O 64-bit executable arm64]
/Applications/Firefox.app/Contents/MacOS/firefox (for architecture x86_64): Mach-O 64-bit executable x86_64
/Applications/Firefox.app/Contents/MacOS/firefox (for architecture arm64): Mach-O 64-bit executable arm64
And here's a library:
$ file /Applications/Firefox.app/Contents/MacOS/libmozglue.dylib
/Applications/Firefox.app/Contents/MacOS/libmozglue.dylib: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit dynamically linked shared library x86_64] [arm64:Mach-O 64-bit dynamically linked shared library arm64]
/Applications/Firefox.app/Contents/MacOS/libmozglue.dylib (for architecture x86_64): Mach-O 64-bit dynamically linked shared library x86_64
/Applications/Firefox.app/Contents/MacOS/libmozglue.dylib (for architecture arm64): Mach-O 64-bit dynamically linked shared library arm64
Update: I checked an M1 Mac, and it looks like it has Intel+ARM fat binaries (which is the same as Big Sur installed on an Intel Mac):
$ file /System/Applications/Chess.app/Contents/MacOS/Chess
/System/Applications/Chess.app/Contents/MacOS/Chess: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64] [arm64e:Mach-O 64-bit executable arm64e]
/System/Applications/Chess.app/Contents/MacOS/Chess (for architecture x86_64): Mach-O 64-bit executable x86_64
/System/Applications/Chess.app/Contents/MacOS/Chess (for architecture arm64e): Mach-O 64-bit executable arm64e
Note that the architecture is listed as "arm64e". The "e" is a subarchitecture indicator; see this question for more info. Looking at /usr/share/file/magic/mach (which holds the magic codes file uses to recognize these file types), there's also an "arm64_v8" subarchitecture (which I think this question addresses).
And just for fun, here's the Chess app from way back in OS X v10.5, which included native code for both PowerPC and Intel, each in both 32- and 64-bit:
$ file /Applications/Chess.app/Contents/MacOS/Chess
/Applications/Chess.app/Contents/MacOS/Chess: Mach-O universal binary with 4 architectures
/Applications/Chess.app/Contents/MacOS/Chess (for architecture ppc): Mach-O executable ppc
/Applications/Chess.app/Contents/MacOS/Chess (for architecture ppc64): Mach-O 64-bit executable ppc64
/Applications/Chess.app/Contents/MacOS/Chess (for architecture i386): Mach-O executable i386
/Applications/Chess.app/Contents/MacOS/Chess (for architecture x86_64): Mach-O 64-bit executable x86_64
- 33,702
-
2Nice call out of older SDK - I’ll edit my answer to “currently being built” since Macs have major architectures from 68000 -> PPC -> Intel -> Apple Silicon as well as 64 bit targets for some of the above. – bmike Oct 20 '21 at 09:34
-
@bmike however I suspect file might not recognise macOS 68000 but only NexTStep 68000 (and hppa and sparc - and unreleased 88000) – mmmmmm Oct 20 '21 at 10:26
-
2@mmmmmm You're right,
filewon't recognize either of the formats Apple used for 68000 binaries. Apple never used the Mach-O formats for 68k code; Mach-O came in with the OS X transition, by which time they'd fully transitioned to PPC hardware.filedoes recognize the "Preferred Executable Format" (PEF) supported for PPC binaries on later classic Mac OS and early OS X versions, but not the even earlier CFM (code fragment manager, used for both 68k and PPC) and CODE resource (even older, 68k only) formats. IDing CFM and CODE formats takes looking at the resource fork, andfiledoesn't. – Gordon Davisson Oct 20 '21 at 19:48
On macOS you can have three flavors of app currently being built, A, B and AB. lipo reveals the build steps the developer chose.
% lipo -archs /System/Applications/Mail.app/Contents/MacOS/Mail
x86_64 arm64
Apple documents this in a long article — jump to the part where it describes the command line build steps for the two “flavors” of current binary and the lipo command that mixes a universal binary from the two. The -target is what results in a binary being a specific format (not just x86_64 but Apple and tied to a specific version of macOS SDK)
x86_app: main.c
$(CC) main.c -o x86_app -target x86_64-apple-macos10.12
arm_app: main.c
$(CC) main.c -o arm_app -target arm64-apple-macos11
universal_app: x86_app arm_app
lipo -create -output universal_app x86_app arm_app
To see the architectures present in a built executable file, run the
lipoorfilecommand-line tools.
Note, the tools work on binaries embedded in the app framework as opposed to the app folder/package that most people call "the app".
The file command is more verbose so I prefer lipo for scripting checks or getting details of a binary.
- 235,889
-
18
-
2I see it at the core of the issue. Apple only documents the architectures in dev docs and Apple directly answers which official command line tools identify a binary format. – bmike Oct 20 '21 at 11:54
-
2I have added commentary on using
liposhowing how terse it is compared tofile- @benwiggy I appreciate the comments and votes, hopefully this answer is far more useful than version one was. – bmike Oct 21 '21 at 11:39
In addition to the terminal commands provided, some GUI apps for this purpose exist.
- Silicon Info: This app provides a simple menu bar indicator for whether the foreground app is running natively or via Rosetta.
- Silicon: This app scans for all apps and states their cpu compatibility in a searchable list.
- 100,768
- 1,391
You can get CPU type of an executable using objdump tool
objdump -x --macho ./an-exec| grep -A1 cputype
This will show X86_64 for x86 binary and ARM64 for an Apple Silicon binary
Alternatively, you can check the same with file cmd.
file ./an-exec
- For x86 you'll see
Mach-O 64-bit executable x86_64 - For ARM64 (Apple Silicon) you'll see
Mach-O 64-bit executable arm64 - For universal binary you'll see
Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64] [arm64:Mach-O 64-bit executable arm64]
- 5,623
- 131