Skip to content

fix(build): only bundle SDL3 when SDL2 is sdl2-compat - #188

Closed
DrDavidL wants to merge 1 commit into
swellweb:maint-3.5from
DrDavidL:fix/build-script-optional-sdl3
Closed

DrDavidL wants to merge 1 commit into
swellweb:maint-3.5from
DrDavidL:fix/build-script-optional-sdl3

Conversation

@DrDavidL

@DrDavidL DrDavidL commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Problem

TargetBridge-Receiver/scripts/build_tbreceiver_c_app.sh unconditionally copies libSDL3.dylib into the app bundle, and exit 1s when it is not found:

SDL3_DYLIB="$(brew --prefix sdl3)/lib/libSDL3.dylib"
if [[ ! -f "$SDL3_DYLIB" ]]; then
  echo "SDL3 runtime library not found: $SDL3_DYLIB" >&2
  exit 1
fi

As the surrounding comment explains, this exists because Homebrew's sdl2 alias now resolves to sdl2-compat, which loads SDL3 at runtime via dlopen — a dependency dylibbundler cannot discover.

That is not true everywhere. On a machine where the genuine sdl2 keg is installed (Cellar/sdl2/2.32.10, no sdl3 keg), the bundled libSDL2-2.0.0.dylib has no SDL3 dependency at all, but brew --prefix sdl3 still prints a path for the uninstalled formula, so the file check fails and the script aborts — before the icon, Info.plist, PkgInfo and signing steps. The result is no .app at all, even though the binary compiled fine.

Fix

Inspect the SDL2 that actually landed in Contents/Frameworks and require SDL3 only when that library really references it:

SDL2_IN_APP="$(find "$APP_DIR/Contents/Frameworks" -name 'libSDL2*.dylib' -print -quit)"
if [[ -n "$SDL2_IN_APP" ]] && strings -a "$SDL2_IN_APP" | grep -q 'libSDL3'; then
  # ... existing require-and-copy, unchanged ...
else
  echo "Bundled SDL2 is not sdl2-compat; skipping SDL3 runtime copy."
fi

The check keys off the artifact rather than the Homebrew formula name, so it stays correct if the sdl2 alias changes again.

Behavior on sdl2-compat machines is unchanged: the shim's dylib does reference libSDL3, so the hard failure still fires and a release build there cannot silently ship without the SDL3 runtime.

Verification

Built from this branch (maint-3.5 + this commit) on an Intel iMac, macOS 14 (OCLP), genuine sdl2 2.32.10, ffmpeg 8.1.1, x86_64:

  • make clean && make — clean compile of 3.5.1, including the new libswscale / SystemConfiguration deps (only the pre-existing macOS-11.0-vs-14.0 ld deployment-target warnings)
  • make test — all three suites pass: test_net_parser 67 checks, test_input_queue 562 checks / 0 failures, test_receiver_profile 13 checks
  • ./scripts/build_tbreceiver_c_app.sh — builds TargetBridge Receiver.app 3.5.1; previously aborted at the SDL3 check before producing any bundle
  • otool -L on the bundled executable — no non-system dylibs outside the bundle; libswscale.9.5.101.dylib bundled correctly
  • codesign --verify --deep --strict — passes
  • Launched the bundled app — OpenGL renderer, SDL audio 48 kHz stereo, listening on TCP 54321, and the 3.5.x profile path correctly reports panel=5120x2880 mode=2560x1440 hidpi=1 name=iMac on the 5K iMac

Not verified by me: the sdl2-compat path, since this machine has no sdl3 keg to bundle. That branch is byte-for-byte the original code, just nested under the new condition.

Retargeted from main to maint-3.5: the SDL3 block is byte-identical on main, v3.5.0, v3.5.1-rc.3 and maint-3.5, and maint-3.5 is where 3.5.x work is actually landing. Happy to rebase onto a different base if you'd prefer.

🤖 Generated with Claude Code

The receiver build script unconditionally copied libSDL3.dylib into the
app bundle and exited 1 when it was missing. That assumes Homebrew's
`sdl2` alias resolved to sdl2-compat, which dlopens SDL3 at runtime.

On a machine with the genuine `sdl2` keg installed (no `sdl3` keg), the
bundled SDL2 has no SDL3 dependency, but the script still aborted before
the icon, Info.plist and signing steps, so the .app never got built.

Check the SDL2 that actually landed in Contents/Frameworks for a libSDL3
reference and require SDL3 only then. Machines using sdl2-compat keep the
existing hard failure, so a release build there still cannot silently ship
without the SDL3 runtime.

Verified on an Intel iMac (macOS 14, genuine sdl2 2.32.10): the bundle now
builds, `codesign --verify --deep --strict` passes, `otool -L` shows no
non-system dylibs outside the bundle, and the app launches and listens.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@DrDavidL
DrDavidL force-pushed the fix/build-script-optional-sdl3 branch from f4de28c to 84b3a3d Compare August 29, 2026 02:36
@DrDavidL
DrDavidL changed the base branch from main to maint-3.5 August 29, 2026 02:36
@swellweb

Copy link
Copy Markdown
Owner

Thank you for identifying and validating this Intel SDL2 packaging issue. The compatible solution is now merged in #189: it supports both native SDL2 and sdl2-compat, and validates that the completed bundle has no Homebrew dependencies. Closing this PR as superseded by the unified maintenance fix.

@swellweb swellweb closed this Aug 29, 2026
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.

2 participants