Skip to content

Commit 8d33cd0

Browse files
committed
Support cross-building aarch64 unikernels on macOS
Apple clang emits ELF with `-target aarch64-linux-gnu`, so we can cross-compile unikernels on macOS using ld.lld and llvm-objcopy.
1 parent d31546c commit 8d33cd0

5 files changed

Lines changed: 61 additions & 5 deletions

File tree

.github/workflows/macos.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
name: macOS
2+
on: [push, pull_request]
3+
jobs:
4+
Build:
5+
name: ARM64
6+
runs-on: macos-15
7+
steps:
8+
- name: Checkout code
9+
uses: actions/checkout@v4
10+
- name: Install dependencies
11+
run: brew install llvm
12+
- name: Build
13+
run: |
14+
export PATH="$(brew --prefix llvm)/bin:$PATH"
15+
env TARGET_CC="clang -target aarch64-linux-gnu" \
16+
TARGET_LD=ld.lld TARGET_OBJCOPY=llvm-objcopy \
17+
./configure.sh --prefix="$PWD/_install"
18+
make V=1
19+
make V=1 install

CHANGES.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## Unreleased
2+
3+
- Support cross-building aarch64 unikernels on macOS using the LLVM cross
4+
tools (#641 @samoht)
5+
16
## v0.11.0 (2026-05-28)
27

38
- Lint our codebase with few warnings (@dinosaure, @hannesm, @MisterDA, #632)

GNUmakefile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ tests: bindings elftool
3232
.PHONY: build
3333
ifdef CONFIG_DISABLE_TOOLCHAIN
3434
build: elftool tenders
35+
else ifeq ($(CONFIG_HOST),Darwin)
36+
# macOS host: only the cross toolchain and target bindings are buildable here.
37+
# elftool needs Linux's <elf.h>, and the tenders are Linux/BSD-only.
38+
build: toolchain bindings
3539
else
3640
build: $(SUBDIRS)
3741
endif
@@ -184,6 +188,10 @@ endif
184188
install: MAKECMDGOALS :=
185189
ifdef CONFIG_DISABLE_TOOLCHAIN
186190
install: install-tools install-tenders
191+
else ifeq ($(CONFIG_HOST),Darwin)
192+
# macOS host: no host tools or tenders are built here, only the cross
193+
# toolchain and bindings (see the build target above).
194+
install: install-headers install-toolchain
187195
else
188196
install: install-tools install-tenders install-headers install-toolchain
189197
endif

configure.sh

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,17 @@ case ${HOST_CC_MACHINE} in
294294
echo "#undef HAVE_VMM_H" >tenders/hvt/hvt_openbsd_config.h
295295
fi
296296
;;
297+
arm64-*darwin*|aarch64-*darwin*)
298+
CONFIG_HOST_ARCH=aarch64 CONFIG_HOST=Darwin
299+
# Apple clang emits Mach-O, not ELF, and macOS ships no GNU cross
300+
# binutils, so building the target toolchain and bindings here needs
301+
# an explicit ELF cross compiler. The tenders are Linux/BSD-only and
302+
# are not built on macOS.
303+
[ -z "${TARGET_CC}" ] && \
304+
die "macOS host requires an ELF cross toolchain: set TARGET_CC" \
305+
"(e.g. TARGET_CC='clang -target aarch64-linux-gnu')," \
306+
"TARGET_LD and TARGET_OBJCOPY"
307+
;;
297308
*)
298309
die "Unsupported host toolchain: ${HOST_CC_MACHINE}"
299310
;;
@@ -495,6 +506,15 @@ case ${CONFIG_HOST} in
495506
TARGET_LD_LDFLAGS="-nopie --no-execute-only"
496507
TARGET_CC_CFLAGS="${TARGET_CC_CFLAGS} -fno-emulated-tls"
497508
;;
509+
Darwin)
510+
# Cross-building ELF unikernels from macOS: the LLVM cross tools
511+
# (clang -target, ld.lld, llvm-objcopy) stand in for the GNU binutils
512+
# Apple does not ship. Same ELF build-id/-no-pie handling as the Linux
513+
# "cc as linker" case.
514+
TARGET_LD="${TARGET_LD:-ld.lld}"
515+
TARGET_OBJCOPY="${TARGET_OBJCOPY:-llvm-objcopy}"
516+
TARGET_CC_LDFLAGS="-Wl,--build-id=none,-no-pie"
517+
;;
498518
*)
499519
die "Unsupported host system: ${CONFIG_HOST}"
500520
;;

opam/solo5-cross-aarch64.opam

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,18 @@ bug-reports: "https://github.com/solo5/solo5/issues"
1010
license: "ISC"
1111
dev-repo: "git+https://github.com/solo5/solo5.git"
1212
build: [
13-
["env" "TARGET_CC=aarch64-linux-gnu-gcc" "TARGET_LD=aarch64-linux-gnu-ld" "TARGET_OBJCOPY=aarch64-linux-gnu-objcopy" "./configure.sh" "--prefix=%{prefix}%"]
13+
["env" "TARGET_CC=aarch64-linux-gnu-gcc" "TARGET_LD=aarch64-linux-gnu-ld" "TARGET_OBJCOPY=aarch64-linux-gnu-objcopy" "./configure.sh" "--prefix=%{prefix}%"] {os != "macos"}
14+
["env" "TARGET_CC=clang -target aarch64-linux-gnu" "TARGET_LD=ld.lld" "TARGET_OBJCOPY=llvm-objcopy" "./configure.sh" "--prefix=%{prefix}%"] {os = "macos"}
1415
[make "V=1"]
1516
]
16-
install: [make "V=1" "install-toolchain"]
17+
install: [
18+
[make "V=1" "install-toolchain"]
19+
[make "V=1" "install-headers"] {os = "macos"}
20+
]
1721
depends: [
1822
"conf-pkg-config" {build & os = "linux"}
1923
"conf-libseccomp" {build & os = "linux"}
20-
"solo5" {= version}
24+
"solo5" {= version & os != "macos"}
2125
]
2226
depexts: [
2327
["linux-headers"] {os-distribution = "alpine"}
@@ -27,8 +31,8 @@ depexts: [
2731
["gcc-aarch64-linux-gnu"] {os-family = "debian"}
2832
]
2933
available: [
30-
(arch != "arm64") &
31-
(os = "linux" & os-family = "debian")
34+
((arch != "arm64") & (os = "linux" & os-family = "debian"))
35+
| (os = "macos" & arch = "arm64")
3236
]
3337
synopsis: "Solo5 sandboxed execution environment"
3438
description: """

0 commit comments

Comments
 (0)