Swift Cross Compile to Single Linux Binary

How to build a swift executable for Linux on macOS

This just means it couldn't locate the linked library. If your libswiftCore.so located at /usr/lib/swift/linux you can run LD_LIBRARY_PATH=/usr/lib/swift/linux ./<your executable for linux> and it will work like a charm.

You can also set LD_LIBRARY_PATH variable to just execute the binary.

Build Apple Silicon binary on Intel machine

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
./configure CFLAGS='-target arm64-apple-macos' \
--host=aarch64-apple-darwin \


# 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 \

The relink.sh:

set -e

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

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


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

if [ -z "$PREFIX" ]; then

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

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

Is a Linux executable compatible with OS X?

No, Linux and Mac OS X binaries are not cross-compatible.

For one thing, Linux executables use a format called ELF.

Mac OS X executables use Mach-O format.

Thus, even if a lot of the libraries ordinarily compile separately on each system, they would not be portable in binary format.

Furthermore, Linux is not actually UNIX-based. It does share a number of common features and tools with UNIX, but a lot of that has to do with computing standards like POSIX.

All this said, people can and do create pretty cool ways to deal with the problem of cross-compatibility.


Finally, to address your point on byte-code: when making a binary, compilers usually generate machine code that is specific to the platform you're developing on. (This isn't always the case, but it usually is.)

Related Topics

Leave a reply