在Intel机器上构建Apple Silicon二进制文件

26

我该如何在macOS 11(Intel)上编译C项目以在Silicon上运行?

我当前的构建脚本非常简单:

./configure
make
sudo make install

我已经尝试使用--host--target标志与aarch64-apple-darwinarm-apple-darwin,但没有成功。

二进制文件始终默认为x86_64

> file foobar.so
foobar.so: Mach-O 64-bit bundle x86_64

更新: 当指定--host时,似乎找不到cc和gcc。

checking for arm-apple-darwin-cc... no
checking for arm-apple-darwin-gcc... no

你安装了最新的XCode 12吗?这是最低要求。 - selbie
@selbie:这是在GitHub Actions上运行的,Xcode版本为12.2。 - Till
请看我的回答:你可能需要使用 -target arm64-apple-macos11。请注意,目标参数前面只有一个破折号,而不是两个。 - selbie
你能编译成 ARM 平台的吗? - Desert Rose
不,我们最终租用了一台MacStadium M1机器,但仍需要在x84上为arm编译此代码。 ‍♂️ - Till
3个回答

15

我在这个页面上找到了一个提示,建议使用这个:

-target arm64-apple-macos11

当我从我的Mac运行这个:

clang++ main.cpp -target arm64-apple-macos11

生成的 a.out 二进制文件如下所示:

% file a.out
a.out: Mach-O 64-bit executable arm64

我已经安装了XCode 12.2。

我面前没有Arm Mac,所以我假设这个可以工作。


你可能不需要这样做。Clang是默认的编译器,而g++命令行只是一个将请求转发到clang的接口。 - selbie
很不幸,由于我们有几个标志,我们必须使用./configure。有没有办法告诉./configure使用clang++ - Till
1
我不是autoconf的专家(这是生成configure脚本的工具)。 但你可能只需要将脚本设置为CC=clangCXX=clang++ - selbie
我们尝试过了,但没有成功。Autotools ‍♂️ - Till
@AlecJacobson - 你是否使用最新版本的XCode?并且安装了所有最新的命令行工具吗? - selbie
显示剩余3条评论

6
我们最终解决了这个问题,并且能够在 GitHub Actions 的 x86-64 机器上编译 darwin-arm64debian-aarch64 二进制文件。
我们预先为 arm64 编译了所有依赖项,并将它们静态和动态链接。
export RELAY_DEPS_PATH=./build-deps/arm64
export PKG_CONFIG_PATH=./build-deps/arm64/lib/pkgconfig

cd ./relay-deps
TARGET=./build-deps make install

cd ./relay
phpize
./configure CFLAGS='-target arm64-apple-macos' \
  --host=aarch64-apple-darwin \
  --enable-relay-jemalloc-prefix
  [snip...]

make

# Dynamically linked binary
cc --target=arm64-apple-darwin \
  ${wl}-flat_namespace ${wl}-undefined ${wl}suppress \
  -o .libs/relay.so -bundle .libs/*.o \
  -L$RELAY_DEPS_PATH/lib -lhiredis -ljemalloc_pic [snip...]

# re-link to standard paths
./relay-deps/utils/macos/relink.sh .libs/relay.so /usr/local/lib
cp .libs/relay.so modules/relay.so

# Build a statically linked shared object
cc --target=arm64-apple-darwin \
  ${wl}-flat_namespace ${wl}-undefined ${wl}suppress \
  -o .libs/relay-static.so -bundle .libs/*.o \
  $RELAY_DEPS_PATH/lib/libhiredis.a \
  $RELAY_DEPS_PATH/lib/libjemalloc_pic.a \
  [snip...]

这个relink.sh文件:

#!/bin/bash
set -e

printUsage() {
    echo "$0 <shared-object> <prefix>"
    exit 1
}

if [[ ! -f "$1" || -z "$2" ]]; then
    printUsage
    exit 1
fi

INFILE=$1
PREFIX=$2

links=(libjemalloc libhiredis [snip...])

if [ -z "$PREFIX" ]; then
    PREFIX=libs
fi

for link in ${links[@]}; do
    FROM=$(otool -L "$INFILE"|grep $link|awk '{print $1}')
    FILE=$(basename -- "$FROM")
    TO="$PREFIX/$FILE"

    echo "$FROM -> $TO"
    install_name_tool -change "$FROM" "$TO" "$1"
done

4

Curious 先生对于将代码交叉编译到 M1 也有所关注。一个意外的解决方案是 Zig。它旨在成为最好的 C 交叉编译方式之一,轻松地从 Linux 目标到 M1。

几周前有一系列关于交叉编译到 M1 的直播: 第一部分 展示了如何在现有的 makefile 中使用 Zig 作为交叉编译器,而在 第三部分 中,他们成功演示了在 Linux 上为 M1 编译 Redis。

强烈推荐。


谢谢分享,我今天下午会深入研究Zig! - Till

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接