2

我有一个基本的 C 程序:

#include <stdio.h>

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

当我cc在 Apple Silicon 设备上直接编译它时,它会生成一个arm64可执行文件:

% cc hello.c -o hello

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

% ./hello
Hello, world!

但是,当我通过 CMake 或 Ninja 等构建系统构建它时,它会生成一个 x86_64 二进制文件:

% ./my-build-system

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

我已经验证了构建脚本正在运行的命令与我自己运行的命令相同。如果我复制并粘贴命令并自己运行它,生成的可执行文件又是 arm64。

4

1 回答 1

4

当您的构建命令不包含要构建的体系结构的特定标志时,Apple 提供的编译器工具(例如)会根据调用进程cc的体系结构执行某种自省。这意味着,如果您的构建系统尚未针对 进行本机编译,您可能会看到这种行为,因为编译器会假定您要为 x86_64 构建!arm64

您可以通过使用该arch工具cc在 x86_64 模式下运行可执行文件来证明这一点:

% arch -x86_64 cc hello.c -o hello

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

作为一种解决方法,您可以引入一个始终重置为本机架构的 shim 编译器。将其另存为force-arm64-cc并使其可执行:

#!/usr/bin/env bash

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

然后,您可以使用此 shim 代替cc

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

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

正确的长期解决方案是在编译时指定目标架构:

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

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

但是,当您重建二进制文件时,这目前会产生一个虚假的可执行文件,这在编辑-编译-运行周期中很常见:

% ./hello
zsh: killed     ./hello

也可以看看:

于 2020-11-14T03:22:20.773 回答