Skip to content

darwin host support: native Apple Silicon build (SDL3/Meson, Linux parity) - #761

Open
Depal1 wants to merge 2 commits into
OoliteProject:masterfrom
Depal1:pr-1-darwin-platform
Open

Depal1 wants to merge 2 commits into
OoliteProject:masterfrom
Depal1:pr-1-darwin-platform

Conversation

@Depal1

@Depal1 Depal1 commented Oct 9, 2026 •

Copy link
Copy Markdown

DRAFT: PR #1, darwin host support (Apple Silicon, SDL3/Meson)

Base: master @ 8ffe02d. Branch: pr-1-darwin-platform (cherry-picked from macos-port).
Commits in this PR: db296a4, b30cb54, 0e476d9, d59033c, 02e861e, 65a95b5, 2714cbf, 4650ff9, 3cf7ab8, f4a93a8, ce78690, 73541bc, f9ff4f7, 54ff50f, 289905e, f3d809b, 672501b, 0e681d3, f91f4a0, 1568866, 349ea6b (21 commits, ~70 files).
Depends on: nothing in-tree (the js artifact arrives in PR #2; this PR's build is verified against a staged copy).


What this adds

A darwin (Apple Silicon) build host for the existing Meson + SDL3 stack, and the source
changes needed to run the game on macOS at feature parity with the Linux build.

Build system. A clang-darwin.ini native file (Apple's toolchain has no lld, and
the thinlto cache flag the Linux branch passes is lld-only; darwin gets ld64's
-cache_path_lto spelling instead). mk.sh picks the native file by host. src/meson
gains a darwin subdir: framework linkage, -DOOLITE_SDL=1, and the js artifact scan.
The GNUstep runtime defines stay Linux-only. All changes are darwin-conditional or
provably identical on Linux (verified per hunk; the post_build script split is pure code
motion into per-platform functions).

Source re-gate: Master's OOLITE_MAC_OS_X branches carried Cocoa-era code behind
headers this tree no longer has (src/Cocoa was removed in #729; main() was entirely
GNUstep-gated, so an Apple-Foundation compile produced an empty main). This PR
introduces OOLITE_MAC_APPKIT (OOLITE_MAC_OS_X && !OOLITE_SDL, defined once in
OOFoundation.h) and moves the backend regions behind it: 28 gate sites across
GameController, the speech backend, the fullscreen controller and the OXP verifier. What
remains on OOLITE_MAC_OS_X is Apple-Foundation idiom only (plist handling, log
routing, sysctl/mach code), which is exactly what the darwin build wants. main()
becomes a real SDL3 entry point. OOFullScreenController.m joins the build (it was in
no source list). Roughly 275 changed lines of re-gate; the rest of the diff is the
legacy-GL layer below.

Renderer legacy-GL layer: Master's renderer hard-requires GL 3.3
(OOOpenGLExtensionManager raises otherwise) and the 1.92 postFX pipeline is GLSL-330
with float MSAA FBOs, VAOs and MRT on the default shader path. macOS offers GL 2.1
(legacy) or 4.1 (core) with no compatibility profile, so neither half of the renderer
survives unmodified. On darwin only, this PR replaces the version gate with capability
tests (2.1 + EXT_framebuffer_object), forces the non-MSAA FBO path (the MSAA-off
configuration already existed), drops to DEPTH_COMPONENT24, adds runtime RGBA16F-to-RGBA8
and single-target-MRT fallbacks wired into the existing completeness checks, removes the
postFX VAOs, and carries GLSL-120 variants of the three postFX shaders behind
OO_LEGACY_GL. Non-darwin keeps #version 330 and the original shader text
byte-identical; on Linux the postFX pipeline is untouched. Effect on macOS: the game
boots in under a second and the full flow (menu, dock, launch, flight, death, menus,
color-blind toggles) renders with ACES, bloom and the postFX chain. True HDR output
stays Windows-only, as on Linux; that arrives for macOS with the SDL_GPU migration
(#579), whenever that happens.

Audio, hardening, packaging: espeak-ng is the speech backend (per the #721
discussion; the NSSpeechSynthesizer region is gated off). The post_build script is split
into per-platform functions with the darwin pieces (Contents layout, dylib bundling via
otool with @rpath rewrites, ad-hoc re-signing after every Mach-O edit, dsymutil/strip),
plus fixes to GNU-only shell constructs that broke on BSD userland. Also: a v-sync fix
(SDL's swap-interval path does not work over NSOpenGLContext on this OS; darwin gets
refresh-period pacing, measured 73-75 fps on a 75 Hz display vs ~220 unpaced), a fix for
a startup stall when the debug console is attached (Apple Foundation's NSInputStream
-read: blocks when drained, where GNUstep returns; the drain loop now honors
hasBytesAvailable), and a portable NSString selector in the HDR snapshot path.

Relation to open issues

  • Apple silicon release #721 asked for an Apple Silicon release and named the restrictions this PR follows:
    SDL3 for windowing (the binary links no AppKit; verified with otool), meson as the
    build system (no Xcode project added), espeak-ng for speech (the Mac synthesizer is
    gated off), and OS-specific code kept to a minimum (measured above; all of it
    darwin-conditional). This PR satisfies those restrictions; the js dependency update
    Apple silicon release #721 also requires is PR Mac-only: bug with interlaced textures #2.
  • ARM Mac build is broken. #360 listed the 2020 blockers for an ARM Mac build. All three are addressed here or in
    PR Mac-only: bug with interlaced textures #2: the arm64 libjs build (PR Mac-only: bug with interlaced textures #2's patches), the ARCHS/xcconfig problem (moot; no
    Xcode build), and the new-clang warnings (the port compiles with zero new warning
    categories; the 151 remaining are pre-existing upstream patterns, counted in the
    validation pack).
  • Translate ObjC code to C++ #569 (ObjC to C++): if that effort lands, the Foundation dependency this PR re-gates
    goes away. The re-gate is mechanical and darwin-conditional; it should not conflict.
  • Split MyOpenGLView into two  #730 (MyOpenGLView split): the GL-glue area this PR touches was refactored recently;
    the PR is based on a current master commit and is expected to need trivial rebases at
    most.

Verification

  • ./mk.sh setup dev, build dev, build debug, build deployment (LTO + strip) all
    green on macOS 26 / Xcode 26.6 / arm64.
  • 82-minute scripted soak, 11 game processes, zero crashes; preference persistence
    round-trip; save/load via console; debug console protocol works (a startup stall when
    the console is attached turned out to be a real bug and is fixed here).
  • Linux/Windows: every hunk is darwin-conditional or provably identical on Linux
    (statement-by-statement code-motion check for the script split; the preprocessed
    shader input for non-darwin is byte-identical to master, verified by extraction).
  • Joystick support: compiled and initialized through SDL3, but NOT tested with
    physical hardware. No joystick was attached during validation, so the log
    reports zero sticks. Treat joystick support as untested; the code path is
    the same SDL3 one Linux uses.
  • Warning count on a clean darwin rebuild: 151 in 4 categories, all pre-existing
    upstream patterns (baseline comparison in the validation pack).
  • Evidence: 31 screenshots, 18+ preserved logs, an 11-item validation matrix.

AI-assistance disclosure: developed with AI assistance (GLM-5.3-Flash); verified by the builds/tests described.

Design issue: #760

Depal1 added 2 commits October 8, 2026 23:36
Downloads the mozillajs-macos release artifact (interpreter-only js185 for
aarch64, built from this org's spidermonkey-ff4 source with the pcre regex
path, mirroring the mozillajs-linux flow) and stages include/ + lib into
build/mozilla_js for the Meson darwin scan. Prerequisite for the Apple
Silicon build described in oolite#721; one of the blockers listed in
oolite#360.
…parity with Linux)

Adds darwin as a build host for the existing Meson + SDL3 stack and the
source changes needed to run on Apple Silicon at parity with the Linux
build. Prepared against oolite#721 and oolite#360; see the design issue for
the full validation evidence.

Build system:
- clang-darwin.ini native file (no lld on macOS; the thinlto cache flag is
  lld-only, darwin uses ld64's -cache_path_lto spelling)
- mk.sh selects the native file by host; get_version.sh made
  bash-3.2/BSD-date portable (Linux output byte-identical)
- src/meson/darwin: framework linkage, -DOOLITE_SDL=1, Apple-Foundation
  defines, js artifact scan (js_static), @executable_path/../Frameworks
  rpath; GNUstep runtime defines stay Linux-only
- Meson LTO cache flag host-guarded (lld-only spelling broke darwin linking)

Source re-gate:
- OOLITE_MAC_APPKIT (OOLITE_MAC_OS_X && !OOLITE_SDL) defined once in
  OOFoundation.h; 28 Cocoa-backend gate sites moved onto it (GameController,
  speech, fullscreen controller, OXP verifier). OOLITE_MAC_OS_X now carries
  only Apple-Foundation idioms. main() becomes a real SDL3 entry point.
  The binary links no AppKit (otool-verified).

Renderer legacy-GL layer (darwin only; Linux/Windows still require GL 3.3
and compile the original GLSL-330 shaders byte-identically):
- capability gate replaces the 3.3 version check (2.1 + EXT_framebuffer_object)
- non-MSAA FBO path; DEPTH_COMPONENT24; runtime RGBA16F->RGBA8 and
  single-target-MRT fallbacks wired into the existing completeness checks
- VAOs removed from the postFX quad (explicit attribute arrays)
- GLSL-120 variants of the three postFX shaders behind OO_LEGACY_GL
  (non-darwin preprocessed shader input byte-identical to master)
- dFdx/dFdy specular filter gated; glClampColor guarded out
- CFBundleVersion in the bundle plist (ResourceManager version gate)

Audio/hardening/packaging:
- espeak-ng speech active on darwin (NSSpeechSynthesizer region gated off,
  per the OoliteProject#721 discussion); OpenAL Soft linked
- post_build split into per-platform functions; darwin fn assembles a real
  Contents/ bundle, bundles non-system dylibs with @rpath, ad-hoc re-signs
  every Mach-O after edits, dsymutil/strip; meson install skipped on darwin
- console-attached startup stall fixed (Apple NSInputStream -read: blocks
  when drained; GNUstep returns)
- v-sync via refresh-period swap pacing (SDL_GL_SetSwapInterval is not
  enforced over NSOpenGLContext on this OS); ~74 fps on a 75 Hz display
- portable NSString selector + removeItemAtPath:error: (upstream-quality)
- ResourceManager builtInPath fall-through fix on the Mac arm
  (upstream-quality)

Known limitations (documented in Documentation/BUILDING-macOS.md):
- Joystick support is compiled and initialized through SDL3 but has NOT been
  tested with physical hardware; the validation log reports zero sticks
  because none was attached. Treat joystick support as untested.
- True HDR output remains Windows-only upstream; macOS renders the same SDR
  ACES/bloom/postFX output as Linux.
- The SpiderMonkey js185 dependency is built interpreter-only with pcre
  regexes on arm64 (no JIT backend exists in js185 for this architecture);
  delivered by the companion SpiderMonkey PRs + mozillajs-macos artifact
  (PR OoliteProject#2). Native arm64 interpreter benchmarks faster than the x86_64
  Rosetta path in all harness kernels.

Validation: 82-minute scripted soak, 11 game processes, zero crashes;
preference persistence and save/load round-trips verified (including a
1.90-mac commander); 6 real OXPs installed and booted with zero JS errors.
Full evidence pack in the series design issue.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant