简体   繁体   中英

Why does my native application compiled on Apple Silicon sometimes build as arm64 and sometimes build as x86_64?

I have a basic C program:

#include <stdio.h>

int main() {
  printf("Hello, world!\n");
}

When I compile this directly using cc on an Apple Silicon device, it produces an arm64 executable:

% cc hello.c -o hello

% file hello
hello: Mach-O 64-bit executable arm64

% ./hello
Hello, world!

However, when I build it through a build system such as CMake or Ninja, it produces an x86_64 binary:

% ./my-build-system

% file hello
hello: Mach-O 64-bit executable x86_64

I've verified that the command that the build script is running is identical to the one that I run myself. If I copy and paste the command and run it myself, the produced executable is again arm64.

When your build command doesn't include specific flags for which architecture to build for, the compiler tools provided by Apple, like cc , perform some kind of introspection based on the architecture of the calling process . That means that if your build system has yet to be natively compiled for arm64 , you might see this behavior as the compiler will assume you want to build for x86_64!

You can demonstrate this by using the arch tool to run the cc executable in x86_64 mode:

% arch -x86_64 cc hello.c -o hello

% file hello
hello: Mach-O 64-bit executable x86_64

As a work-around, you can introduce a shim compiler that always resets to the native architecture. Save this as force-arm64-cc and make it executable:

#!/usr/bin/env bash

# Note we are using arm64e because `cc` does not have an arm64 binary!
exec arch -arm64e cc "$@"

You can then use this shim in place of cc :

% CC=$PWD/force-arm64-cc ./my-build-system

% file hello
hello: Mach-O 64-bit executable arm64

The correct long term solution is to specify the target architecture when compiling:

% arch -x86_64 cc -arch arm64 hello.c -o hello

% file hello
hello: Mach-O 64-bit executable arm64

However, this currently produces a bogus executable when you rebuild the binary, which is quite common in an edit-compile-run cycle:

% ./hello
zsh: killed     ./hello

See also:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM