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
Debug and Test Your CodeApple silicon supports all debugging and testing tools found on Intel-based Mac computers. Use the Xcode IDE to set and monitor breakpoints and monitor other aspects of your app's behavior. Use lldb from the command line to perform similar tasks outside of the Xcode interface.
Xcode automatically creates a binary slice optimized for Apple silicon Macs and another for Intel-based Macs, then puts them together as a single app bundle thats ready to distribute or submit to the Mac App Store. Optimize for the new MacBook Pro display.
The Mac transition to Apple silicon is the process of changing the central processing units (CPUs) of Apple Inc.'s line of Mac computers from Intel's x86-64 processors to Apple-designed systems on a chip that use the ARM64 architecture.
A universal binary runs natively on both Apple silicon and Intel-based Mac computers, because it contains executable code for both architectures.
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.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With