Skip to content

sdl: consume SDL3 from the SDK - #2176

Draft
edumeneses wants to merge 3 commits into
masterfrom
sdl3
Draft

sdl: consume SDL3 from the SDK#2176
edumeneses wants to merge 3 commits into
masterfrom
sdl3

Conversation

@edumeneses

@edumeneses edumeneses commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

The score half of the SDL3 move. Third of three:

Depends on ossia/libossia#922; the submodule bump here points at that branch, so this can't merge before it.

What changed

  • SDK prefix paths: $OSSIA_SDK/SDL2*$OSSIA_SDK/SDL3* in CMakeLists.txt and cmake/ScoreExternalAddon.developer.cmake
  • ossia::sdl2ossia::sdl3 in score-plugin-audio
  • -sUSE_SDL=2-sUSE_SDL=3 in src/app/CMakeLists.txt
  • libossia submodule → the SDL3 branch

The submodule bump also picks up the 13 commits of libossia master the pin was behind. None of them touch SDL (two touch audio, both miniaudio).

Nothing else needed changing

joystick_info deliberately kept its index-based API in ossia/libossia#922, so the enumeration loops in JoystickDevice.cpp / JoystickProtocolFactory.cpp and the (id, index) pair in JoystickSpecificSettings are untouched — existing save files keep loading.

avendish is deliberately untouched. avendish.ossia.cmake and avendish.standalone.cmake do reference a bare SDL2 link target, but every one of those sits behind either the if(1) short-circuit at the top of avendish.ossia.cmake or an if(TARGET ossia::ossia) that score's build never enters. I checked a configured build: no link.txt mentions SDL2, and the only libSDL2.so in build.ninja comes from system ffmpeg's avdevice pkg-config ldflags — unrelated. So this stays a two-repo change rather than needing a celtera/avendish PR.

Testing (linux-x86_64, SDL3 3.4.14)

Every affected TU compiles clean under this build's real flags and warnings:

  • JoystickDevice.cpp
  • JoystickProtocolFactory.cpp
  • JoystickProtocolSettingsWidget.cpp
  • JoystickSpecificSettingsSerialization.cpp
  • score_plugin_audio.cpp (the TU that pulls in Audio/SDLInterface.hpp)

Runtime behaviour of the two rewritten paths is verified in ossia/libossia#922.

Packaging targets that don't use the SDK

The prefix-path change only covers $OSSIA_SDK consumers. Two other paths resolve SDL elsewhere and needed fixing, or they silently lose the joystick protocol and the SDL audio engine:

  • flatpak had no SDL module at all — it was taking SDL2 from the org.kde.Platform runtime. Every other non-runtime dep in that manifest is bundled (portaudio, boost, faust, ysfx, …), so modules/sdl3.yaml bundles SDL3 the same way, with the SDK's subsystem set.
  • distro legs — of the ones with an active libsdl2-dev, only some releases actually ship libsdl3. Verified against the Debian and Launchpad archives:
release libsdl3 action
Debian trixie 3.2.10 libsdl3-dev
Debian sid 3.4.14 (covered by trixie)
Ubuntu plucky 3.2.8 libsdl3-dev libsdl3-0
Ubuntu questing / 26.04 3.2.20 libsdl3-dev libsdl3-0
Ubuntu jammy, noble, lunar, oracular none left on SDL2
Debian bookworm, bullseye none already had SDL commented out

nix moves to the SDL3 attribute.

Ubuntu jammy (22.04 LTS), noble (24.04 LTS), lunar and oracular will build without the joystick protocol — those releases have no libsdl3 to point at. Needs a call on whether to build SDL3 from source in their deps scripts.

A correction worth recording

I initially expected these legs to fail rather than degrade, because they set SCORE_DEPLOYMENT_BUILD=1 and ScoreFeatureCheck.cmake does score_assert_feature(sdl) with a FATAL_ERROR. That assert is a no-op:

function(score_assert_feature name)
  if(NOT "${name}" IN_LIST "${SCORE_FEATURES_LIST}")
    list(APPEND SCORE_MISSING_FEATURES "${name}")   # no PARENT_SCOPE
  endif()
endfunction()

list(APPEND) in a function() without PARENT_SCOPE never reaches the variable the FATAL_ERROR tests, and IN_LIST is given a dereferenced "${SCORE_FEATURES_LIST}" where it wants the list's name. Verified with a minimal CMake repro. Same for score_assert_plugin. It also explains how the Debian legs pass today with their SDL lines commented out.

Not fixed here on purpose — it's an unrelated latent bug and repairing it would turn several legs red simultaneously. Happy to open a separate issue.

Not covered

No gamepad on the test machine, so rumble/sensors/touchpad are compile- and API-verified only. And a full SDK-based build needs an SDK carrying SDL3, which is why ossia/sdk#27 lands first.

🤖 Generated with Claude Code

https://claude.ai/code/session_01TTUi76cnUWh7dGZC64LqbZ

edumeneses and others added 2 commits August 6, 2026 09:45
Points the SDK prefix paths at $OSSIA_SDK/SDL3 (see ossia/sdk#27), renames the
ossia::sdl2 link target to ossia::sdl3, moves the Emscripten link option to
-sUSE_SDL=3, and bumps libossia to the branch carrying the API port.

The libossia bump also picks up the 13 commits of master the submodule was
behind; none of them touch SDL.

avendish is deliberately untouched. avendish.ossia.cmake and
avendish.standalone.cmake do reference a bare SDL2 link target, but every one of
those references sits behind either the `if(1)` short-circuit at the top of
avendish.ossia.cmake or an `if(TARGET ossia::ossia)` that score's build does not
enter -- no link.txt in a configured score build mentions SDL2, and the only
libSDL2.so left in build.ninja comes from system ffmpeg's avdevice pkg-config
ldflags, which is unrelated.

Verified on linux-x86_64 against SDL3 3.4.14: JoystickDevice.cpp,
JoystickProtocolFactory.cpp, JoystickProtocolSettingsWidget.cpp,
JoystickSpecificSettingsSerialization.cpp and score_plugin_audio.cpp (which is
what pulls in Audio/SDLInterface.hpp) all compile clean under this build's own
flags and warnings. joystick_info keeps its index-based API, so the enumeration
loops in JoystickDevice and JoystickProtocolFactory and the (id, index) pair in
JoystickSpecificSettings needed no change and existing save files keep loading.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TTUi76cnUWh7dGZC64LqbZ
…aries

The prefix-path change only covers builds that consume $OSSIA_SDK. The flatpak
and the distro legs resolve SDL from elsewhere, and find_package(SDL3) finds
nothing there, which silently turns OSSIA_ENABLE_SDL off and drops the joystick
protocol and the SDL audio engine from those artefacts.

The flatpak had no SDL module at all: it was picking SDL2 up from the
org.kde.Platform runtime. Every other non-runtime dependency in that manifest is
bundled (portaudio, boost, faust, ysfx, ...), so SDL3 is bundled the same way,
built with the same subsystem set the SDK uses.

For the distro legs, libsdl3 exists in Debian trixie (3.2.10) and sid (3.4.14)
and in Ubuntu plucky (3.2.8) and questing (3.2.20), so those move to
libsdl3-dev/libsdl3-0, and nix moves to the SDL3 attribute.

Ubuntu jammy, noble, lunar and oracular are deliberately left alone: none of
those releases ship libsdl3 at all, so there is nothing to point them at. They
will build without the joystick protocol until someone decides whether to build
SDL3 from source in their deps scripts. Debian bookworm/bullseye/trixie already
had their libsdl2 lines commented out, so nothing changes for them.

Note this is a silent downgrade rather than a build failure, despite
score_assert_feature(sdl) and SCORE_DEPLOYMENT_BUILD=1 being set on those legs:
score_assert_feature is currently a no-op. It does list(APPEND
SCORE_MISSING_FEATURES ...) inside a function() with no PARENT_SCOPE, so the
variable the FATAL_ERROR tests is always empty, and it also passes a dereferenced
"${SCORE_FEATURES_LIST}" to IN_LIST, which expects the list's name. Left as-is
here on purpose - fixing it belongs in its own change, and would turn several
legs red at once.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TTUi76cnUWh7dGZC64LqbZ
Ubuntu jammy (22.04 LTS), noble (24.04 LTS), lunar and oracular ship no libsdl3
at all, so pointing them at a package was not an option and they would otherwise
have built with the joystick protocol and the SDL audio engine quietly missing.

ci/sdl3.source.deps.sh builds SDL3 3.4.14 into /usr/local with the same subsystem
set as the SDK's sdl.sh and the flatpak module. It is sourced rather than executed
so $SUDO from common.setup.sh stays in scope, which is also why it contains no
`exit` - that would take the calling deps script down with it and skip
common.deps.sh. It short-circuits on `pkg-config --exists sdl3`, so a release that
gains a libsdl3 package later only needs its apt line changed and the source build
becomes a no-op.

libsdl2-dev/libsdl2-2.0-0 are replaced by libudev-dev on those four: SDL3's linux
joystick and HIDAPI backends want it, and nothing else in the tree needs SDL2 any
more.

Version tracks SDL_VERSION in ossia/sdk's common/versions.sh; keep them in step.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TTUi76cnUWh7dGZC64LqbZ

@jcelerier jcelerier left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

urgh, if ubuntu noble still doesn't have SDL3 then maybe it's still a few years too early to do this. There's a lot of work in score right now towards making sure it can build as-is on distros so this would really break this :/

@edumeneses

Copy link
Copy Markdown
Contributor Author

Fair point, and taken — ci/sdl3.source.deps.sh is exactly the vendoring the build-as-is work is trying to get rid of, so that commit solves the wrong problem. It'll go.

Edu and I discussed this live with you, so to record the resolution here: SDL gets disabled on any build whose distro doesn't ship SDL3. No source builds, no dual SDL2/SDL3 code path. (I did size a dual-version option — SDL_ENABLE_OLD_NAMES covers ~30 of the renames, so the divergence is smaller than it looks — but it's not worth two code paths, so setting it aside.)

Before I rework the PRs, here's the actual per-target picture, since it's a bit better than "noble doesn't have it".

Ships SDL3 — SDL stays enabled

target SDL3
Ubuntu 26.04 LTS (resolute, current stable) 3.4.2
Debian trixie (current stable) / sid 3.2.10 / 3.4.14
Ubuntu 25.04 plucky / 25.10 questing 3.2.8 / 3.2.20
Arch 3.4.14
Homebrew (macOS) 3.4.14
nixpkgs yes
SDK builds (linux/macOS/windows) 3.4.14 via ossia/sdk#27

No SDL3 — SDL disabled

  • Ubuntu 24.04 LTS noble (supported → Apr 2029) and 22.04 LTS jammy (→ Apr 2027). These are the two that actually matter.
  • Ubuntu lunar / oracular — both Obsolete per Launchpad, so the SDL question there is moot either way.
  • Debian bookworm / bullseye — their libsdl2-dev lines are already commented out, so SDL is already disabled on those.
  • Fedora / openSUSE — already disabled by your own -fPIC TODOs.
  • FreeBSD — never installed SDL at all.

So the net change to "builds as-is on distros" is: noble and jammy lose the joystick protocol and the SDL audio engine. Everything else either already had SDL off, or has SDL3 available.

Two things that need your call

1. Flatpak. The org.kde.Platform runtime ships SDL2, not SDL3 — so under the rule as stated, the flatpak would lose SDL. But the flatpak had no SDL module at all before this PR; it was picking SDL2 out of the runtime, and every other non-runtime dep in that manifest is already bundled (portaudio, boost, faust, ysfx, …). Bundling SDL3 there isn't distro vendoring, it's how flatpaks work. I'd keep modules/sdl3.yaml and let the flatpak have gamepad support. Say if you'd rather it just be off.

2. WASM. Emscripten's sdl3 port exists at the EMSDK_VERSION the SDK pins, with SDL_JOYSTICK_EMSCRIPTEN and SDL_AUDIO_DRIVER_EMSCRIPTEN enabled — but it still prints sdl3 port is still experimental and ships 3.4.2. Either we go -sUSE_SDL=3 and accept that, or SDL goes off for browser builds. Your full-WASM-with-SDL3 verification is still the gate here.

Two incidental findings

brew install sdl is already broken. Homebrew has no sdl or sdl2 formula any more — both 404; only sdl12-compat and sdl3 exist. So ci/osx.brew.deps.sh:7 is asking for a formula that doesn't exist. Moving that line to sdl3 fixes a pre-existing bug rather than causing one — flagging it so it doesn't look like collateral damage.

score_assert_feature(sdl) will now be asserting something deliberately false on distro deployment builds. It doesn't bite today because the function is a no-op (list(APPEND ...) inside a function() with no PARENT_SCOPE, plus IN_LIST handed a dereferenced "${SCORE_FEATURES_LIST}" — details in ossia/sdk#27). But if anyone ever fixes that, noble/jammy/bookworm/fedora/suse go red at once. Under this plan it probably wants scoping to SDK builds, or dropping. Happy to do it as a separate PR — not touching it here.

Also worth a message(STATUS ...) when find_package(SDL3) comes up empty, so "no gamepad on noble" is a visible, intentional state rather than something to rediscover later. Will add unless you'd rather not.

Hardware check, since it came up

Edu plugged in a DualShock 4, so the rewritten paths are now verified against real hardware, not just the API: type detected as SDL_GAMEPAD_TYPE_PS4, SDL_OpenGamepad fine, 6 axes and 15 buttons mapped, and the property-based rumble query returns RUMBLE=1 / TRIGGER_RUMBLE=0 — correct for a DS4 versus a DualSense — with SDL_RumbleGamepad accepted. Sensors and touchpad come back empty because those need SDL's HIDAPI driver and /dev/hidraw0 is root-only here; that's a Linux permissions thing, identical under SDL2, not a port regression.

Not touching anything until you ok this — in particular the flatpak and WASM calls above.


Written by Claude (Anthropic), acting as Edu's assistant — Edu has reviewed the analysis above.

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