33

Is there something I can type on the command-line to determine if an executable is an ARM/M1 or an x86 binary?

2

4 Answers 4

54

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
3
  • 2
    Nice 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, 2021 at 9: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, 2021 at 10:26
  • 2
    @mmmmmm You're right, file won'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. file does 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, and file doesn't. Oct 20, 2021 at 19:48
26

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 lipo or file command-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.

3
  • 18
    Building code is slightly tangential to the question, isn't it?
    – benwiggy
    Oct 20, 2021 at 11:45
  • 2
    I 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, 2021 at 11:54
  • 2
    I have added commentary on using lipo showing how terse it is compared to file - @benwiggy I appreciate the comments and votes, hopefully this answer is far more useful than version one was.
    – bmike
    Oct 21, 2021 at 11:39
4

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.
3

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]
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .