Reputation: 1138
How can I compile a C project on macOS 11 (Intel) to work on Silicon?
My current build script is as simple as:
./configure
make
sudo make install
I've tried using the --host
and --target
flags with aarch64-apple-darwin
and arm-apple-darwin
without any luck.
The binary always defaults to x86_64
:
> file foobar.so
foobar.so: Mach-O 64-bit bundle x86_64
UPDATE:
It seems cc and gcc aren't found when --host
is specified.
checking for arm-apple-darwin-cc... no
checking for arm-apple-darwin-gcc... no
Upvotes: 27
Views: 12562
Reputation: 1138
We ended up solving solving this and being able to compile darwin-arm64
and debian-aarch64
binaries on GitHub Actions' x86-64 machines.
We pre-compiled all our dependencies for arm64 and linked them statically as well as dynamically.
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...]
The 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
Upvotes: 6
Reputation: 927
Mr. Curious was curious about cross-compilation to M1 as well. One unexpected solution is Zig. It aims to be the best way to cross-compile C, among other things; it easily targets M1 from Linux.
There was a series of streams about cross compiling to M1 a couple of weeks ago: Part 1 shows how to use Zig as a cross-compiler in existing makefiles, and in Part 3 they successfully demonstrate compiling Redis on Linux for M1.
Highly recommended.
Upvotes: 4
Reputation: 104579
I found a hint on this page to use this:
-target arm64-apple-macos11
When I run this from my mac:
clang++ main.cpp -target arm64-apple-macos11
The resulting a.out binary is listed as:
% file a.out
a.out: Mach-O 64-bit executable arm64
I have XCode 12.2 installed.
I don't have an Arm Mac in front of me, so I'm assuming this works.
Upvotes: 15