Repository navigation
ARM64 (aarch64) Linux host support - #1818
Merged
Merged
Conversation
Top-level CMakeLists.txt:
* detect host arch via `uname -m` so subsequent project() and the
SDK-platform error message recognise aarch64 hosts.
* add TARGET_ARM64 option, defaulted to ON when host is aarch64
(and i386/x86_64 default to OFF in that case).
cmake helpers:
* architecture.cmake: pick APPLE_ARCH_64BIT="arm64" and the matching
triplets when TARGET_ARM64 is on.
* compiler_include.cmake: arm64 triplet handling for the per-arch
compile flags.
basic-headers/arm/arch.h: thin stub matching the existing x86 layout
so anything that does `#include <arm/arch.h>` resolves on arm64 builds.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Apple's MacOSX.sdk ships per-arch include trees: architecture/arm/... arm/... libkern/arm/... mach/arm/... mach/arm64/... All but a handful of these files are thin symlinks (the typical SDK layout where, e.g., arm/_types.h aliases an existing public header). Add them so any source that does `#include <arm/...>` or `#include <mach/arm/...>` resolves on arm64 builds. A couple of `mach/arm/_structs.h` / `mach/arm/thread_status.h` get small adjustments to match the canonical Darwin layout. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add the per-arch libm sources for arm64:
* Source/ARM/arm64_builtins.c — synthesises the builtins Darwin's
libm exposes that LLVM compiler-rt doesn't provide on Linux/arm64.
* Source/ARM/fenv.{c,h}, fpclassify.c, required_arithmetic.h, math.h
— arm-specific implementations of fenv/fpclassify/required_arithmetic
and the public ARM math.h header.
* include/architecture/arm/math.h — symlink to Source/ARM/math.h.
* top-level CMakeLists.txt: wire the ARM/ sources in when
TARGET_ARM64 is on.
Also: Source/complex.h grows an aarch64 branch (was `__arm__` only,
which is 32-bit) so libm/Source/ARM/complex.c (and any consumer of
this header) builds on Linux/aarch64.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add the bits the Mach-O loader needs on arm64:
* include/{arm/cpu_capabilities,libkern/arm/...,mach/arm/...}.h —
the arm-specific helpers that mldr's translation layer needs at
build time on aarch64 hosts.
* elfcalls/threads.c — wire up arm64 thread bootstrap helpers.
* commpage.c — arm64 commpage initialisation.
* mldr.c — branch out for arm64 in entry/setup code.
* loader.c — when loading the Mach-O image on arm64, force the
initial mmap into the low-VA window (<2^47). Linux ARM64 kernels
happily return 48-bit VAs; anything above 2^47 collides with
ObjC's FAST_DATA_MASK (47 bits) and class_initialize SIGSEGVs.
Retry with MAP_FIXED if the kernel hands out a high VA, and bump
a sequential slot so successive loads don't collide.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* frameworks/CoreServices: add reexport_arm64.exp and wire it in
via CMakeLists.txt; Components.h / ComponentManager.cpp small
branch-out for arm64.
* launchd/src/core.c: arm64-conditional adjustment for the spawn
path (kept minimal — see arm64 commit log).
* libelfloader/wrapgen/wrapgen.cpp: arm64-aware codegen tweaks.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…e files Rework the ARM64 libm, choosing each symbol's source deliberately: - clang __builtin_* for ops that lower to single/few ARM64 instructions (sqrt/fabs/ceil/floor/trunc/rint/round/fmin/fmax/fma/lround/llround/ lrint/llrint/copysign). Verified at -O2 to be pure hardware lowering with no self-recursion; drop the old wrappers that fell back to libcalls. - openlibm (FreeBSD msun) C for transcendentals/complex/bessel and for the Apple files that were soft-float-only stubs on arm64 (fmod, modf, exp2). - Apple's own arch-portable implementations kept where valid and without an arm64 perf regression (cbrt, fmodf, log10/log1p via log.c, nextafter[f]). fenv: split the ARM64 declarations out of the Source/fenv.h dispatcher into Source/architecture/arm/fenv.h (+ include/ and SDK symlinks), matching the i386 layout; values are taken verbatim from Apple's shipping arm64 fenv.h. Source/ARM/fenv.h stays a self-contained implementation-private header (like Source/Intel/fenv.h) carrying the mrs/msr FPCR/FPSR accessors. Also: classify backings (__isnan/__isinf/__isfinite/__isnormal/__signbit/ __fpclassify*), legacy + Apple-private wrappers (finite/matherr/rinttol/ roundtol/significand/__inf/__inff/__nan), GNU fenv extensions (fegetexcept/ fesetexcept/__fegetfltrounds), ___Libm_version, and exp2f. Exports/alias are brought to the AMD64 ABI (294/295 symbols; the only gap is the Intel-only __FE_DFL_DISABLE_SSE_DENORMS_ENV). Newly ported openlibm files use fdlibm names (e_/s_/k_) like Source/Intel; pre-existing _freeBSD.c names are kept. deps: fix the migexe -> chmod -> libsyscall -> migexe cyclic dependency in the bootstrap_cmds submodule by invoking /bin/chmod through cmake -E env instead of a bare `chmod` (which CMake bound to the Darling Mach-O chmod target); /bin/chmod also works on cmake 3.18 where `cmake -E chmod` does not. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
clang 16 promoted several long-standing warnings to errors by default: -Werror=implicit-function-declaration -Werror=implicit-int -Werror=int-conversion -Werror=incompatible-function-pointer-types Many of Darling's vendored C sources predate C99 strictness and trip these. Demote them back to warnings inside an `if(clang>=16)` guard so older clangs are unaffected. This unblocks building the rest of the upgrade on amd64 with a modern toolchain (clang-19 in our case); the libcxx-15 bump that follows requires clang-14+ anyway. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The submodule bumps in the posted ARM64 patchset reference commits that only exist in the patch author's forks. Instead, the per-submodule patch series were applied locally onto an arm64-support branch in each submodule, and this commit records those commits. objc4: the "part2" patch (hardcoding OBJC_IS_DEBUG_BUILD) was dropped, since upstream already derives it from NDEBUG. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fseventsd is built for the Darwin target, so <linux/types.h> resolves to the host header, which needs the arch-specific <asm/types.h>. On x86_64 Debian that only works because gcc-multilib installs /usr/include/asm; on aarch64 the build fails. Define the few kernel types used directly. Content matches VibeDarling/darling@9c5adac29 ("compat: Android Bionic libc, signal range, and shared memory adaptations"), which fixed the same problem. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Runtime fixes needed on aarch64 hosts with a 48-bit VA, cherry-picked from the VibeDarling forks (which carry a newer version of this ARM64 port): - darlingserver: don't pack priority_queue child pointers under __DARLING__ (sign-extending 0xaaaa... heap pointers crashed the timer queue) [VibeDarling/darlingserver@3281745c0] - dyld: don't read TPIDRRO_EL0 in _tlv_get_addr; Linux keeps it 0 [VibeDarling/darling-dyld@640b559b8, @fe73598dd] - libffi: cfi_startproc after the label so Mach-O CFI assembles [VibeDarling/darling-libffi@e67f81120] - xnu: low-VA arena uses MAP_FIXED_NOREPLACE instead of clobbering existing mappings, then moved into BSD mmap [VibeDarling/darling-xnu@2c98884, @6bc004a, @499e41d, @e0ee023] Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Nov 6, 2026
Member
Author
Yes, I used Claude to get it running + I told it to check VibeDarling for hints. |
This was referenced Nov 6, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds support for building and running Darling on ARM64 (aarch64) Linux hosts, with native arm64 Mach-O binaries. This supersedes #1753: it contains that PR's base port plus the runtime fixes needed to actually boot the container and run programs.
On an aarch64 host,
darling shellnow starts and runs native arm64 Mach-O binaries: bash, coreutils, pipes and job control,launchctl, Perl 5.18, Ruby 2.6 and Python 2.7.What's in here
Base port (from #1753, by @kkHAIKE)
TARGET_ARM64option, arm/arm64 SDK header links, and framework and tool build adjustments.Runtime fixes (from a follow-up patchset by fervi)
EVFILT_PROCkqueue loop with apoll()+waitpid()loop.sid == 0for darlingserver, and the shellspawn wait timeout is now 60 s.binfmt_misc, a fixeddyld_path, and paths already inside the container are no longer prefixed withSYSTEM_ROOT.Fixes made while bringing this up on a 48-bit-VA aarch64 kernel
linux/fanotify.hno longer includes the host's<linux/types.h>. That include only worked on x86_64 becausegcc-multilibinstalls/usr/include/asm.priority_queuesign-extended heap pointers (0xaaaa…became0xffffaaaa…), and the timer queue crashed._tlv_get_addrreadTPIDRRO_EL0, which Linux always leaves at 0.MAP_FIXEDand silently replaced live mappings. It now usesMAP_FIXED_NOREPLACE.Deviations from the original patches
OBJC_IS_DEBUG_BUILDwas dropped. Upstream already derives it fromNDEBUG(Update objc4 to derive OBJC_IS_DEBUG_BUILD from NDEBUG #1798).arm64-supportbranch in our repos instead (PRs below).CMakeLists.txt: a context conflict with the ObjC-literals block, resolved by hand.Submodule PRs (merge these first)
src/external/IOKitUser: ARM64 (aarch64) Linux host support darling-iokituser#8src/external/bash: ARM64 (aarch64) Linux host support darling-bash#6src/external/bootstrap_cmds: ARM64 (aarch64) Linux host support darling-bootstrap_cmds#10src/external/bzip2: ARM64 (aarch64) Linux host support darling-bzip2#5src/external/cctools-port: ARM64 (aarch64) Linux host support cctools-port#8src/external/cfnetwork: ARM64 (aarch64) Linux host support darling-cfnetwork#5src/external/cocotron: ARM64 (aarch64) Linux host support darling-cocotron#75src/external/corefoundation: ARM64 (aarch64) Linux host support darling-corefoundation#14src/external/darlingserver: ARM64 (aarch64) Linux host support darlingserver#23src/external/dbuskit: ARM64 (aarch64) Linux host support darling-dbuskit#2src/external/dyld: ARM64 (aarch64) Linux host support darling-dyld#8src/external/expat: ARM64 (aarch64) Linux host support darling-expat#3src/external/foundation: ARM64 (aarch64) Linux host support darling-foundation#34src/external/libc: ARM64 (aarch64) Linux host support darling-Libc#6src/external/libffi: ARM64 (aarch64) Linux host support darling-libffi#2src/external/libkqueue: ARM64 (aarch64) Linux host support darling-libkqueue#11src/external/liblzma: ARM64 (aarch64) Linux host support darling-liblzma#3src/external/libmalloc: ARM64 (aarch64) Linux host support darling-libmalloc#4src/external/libplatform: ARM64 (aarch64) Linux host support darling-libplatform#6src/external/libpthread: ARM64 (aarch64) Linux host support darling-libpthread#4src/external/libsystem: ARM64 (aarch64) Linux host support darling-Libsystem#8src/external/libunwind: ARM64 (aarch64) Linux host support darling-libunwind#5src/external/libxpc: ARM64 (aarch64) Linux host support darling-libxpc#11src/external/objc4: ARM64 (aarch64) Linux host support darling-objc4#5src/external/openssl: ARM64 (aarch64) Linux host support darling-openssl#5src/external/perl: ARM64 (aarch64) Linux host support darling-perl#6src/external/ruby: ARM64 (aarch64) Linux host support darling-ruby#5src/external/security: ARM64 (aarch64) Linux host support darling-security#8src/external/sqlite: ARM64 (aarch64) Linux host support darling-sqlite#2src/external/xnu: ARM64 (aarch64) Linux host support darling-xnu#29src/external/zlib: ARM64 (aarch64) Linux host support darling-zlib#3arm64-supportbranches. If the submodule PRs are squash- or rebase-merged, the commits get new SHAs and this PR needs a bump before it merges. A plain merge commit keeps the SHAs.Testing
darling shellruns:uname,sw_vers,ls, pipes, background jobs,file(it reportsMach-O 64-bit executable arm64),sysctl,launchctl list, and Perl, Ruby and Python one-liners.__aarch64__/__arm64__/TARGET_ARM64guards, but this still needs an x86_64 build and smoke test before merge.Known issues (follow-ups)
defaultsCLI: the tool is GNUstep's, so it doesn't accept macOS type flags (-string,-int,-bool,-array,-dict-add, …), anddefaults read domain keyprintsdomain key valueinstead of just the value. Persistence itself is fixed here; see the foundation PR.Fixed since this PR was opened: the cross-thread TSD mix-ups and main-thread TSD registration (xnu + dyld),
hw.machine/uname -mnow reportarm64,NSUserDefaultspersistent domains (defaults writenow persists), libpthread's____chkstk_darwinno longer readsTPIDRRO_EL0, andtools/shutdown-user.sh(run byninja install) no longer hangs on, and now actually stops, containers in a non-defaultDPREFIX. An interactive shell in a pty now works:tty/ttyname()find/dev/pts/N, andtcsetattr()no longer resets the line speed to B0 (generic bugs, not arm64-specific).Provenance
git cherry-pick -xand credited in the commit messages.TPIDRRO_EL0semantics,MAP_FIXED_NOREPLACE) and from the XNUpriority_queuesource that is already in our tree.🤖 Generated with Claude Code