From ac9d2f8648cecb4f7860acf62598a7757dc56146 Mon Sep 17 00:00:00 2001 From: Colin Sames Date: Fri, 3 Apr 2026 19:23:53 +0200 Subject: [PATCH] Experimental support for SDL_mixer Now working. We need support for SDL 3.4.0 but current wayland dependency is not fulfilled. --- CMakeLists.txt | 7 +- cmake/SDLMixerSetup.cmake | 46 ++++++++++++ engine/CMakeLists.txt | 5 +- prebuilt/linux/SDL3-dynamic/lib/libSDL3.so | 2 +- prebuilt/linux/SDL3-dynamic/lib/libSDL3.so.0 | 2 +- scripts/bootstrap_sdl_mixer_linux.sh | 73 ++++++++++++++++++++ scripts/bootstrap_sdl_mixer_windows.ps1 | 66 ++++++++++++++++++ 7 files changed, 194 insertions(+), 7 deletions(-) create mode 100644 cmake/SDLMixerSetup.cmake create mode 100644 scripts/bootstrap_sdl_mixer_linux.sh create mode 100644 scripts/bootstrap_sdl_mixer_windows.ps1 diff --git a/CMakeLists.txt b/CMakeLists.txt index 07c8c01..7abec81 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,11 +15,12 @@ endif() message(STATUS "Build config: PLATFORM=${PLATFORM}, SDL_LINK_TYPE=${SDL_LINK_TYPE}, BUILD_TYPE=${CMAKE_BUILD_TYPE}") -# --- Resolve SDL --- +# --- Resolve libraries --- include(cmake/SDLSetup.cmake) +#include(cmake/SDLMixerSetup.cmake) -# --- Apply Linux dynamic RPATH globally so all targets can find libSDL3.so.0 -# at runtime. SDL_LINUX_RPATH is set by SDLSetup.cmake only on Linux + dynamic. +# --- Apply Linux dynamic RPATH globally so all targets can find shared libs +# at runtime. SDL_LINUX_RPATH is appended to by each Setup module. if(DEFINED SDL_LINUX_RPATH) message(STATUS "Setting CMAKE_BUILD_RPATH to: ${SDL_LINUX_RPATH}") set(CMAKE_BUILD_RPATH "${SDL_LINUX_RPATH}") diff --git a/cmake/SDLMixerSetup.cmake b/cmake/SDLMixerSetup.cmake new file mode 100644 index 0000000..b0c14af --- /dev/null +++ b/cmake/SDLMixerSetup.cmake @@ -0,0 +1,46 @@ +# Resolves pre-built SDL2_mixer libraries based on PLATFORM and SDL_LINK_TYPE. +# +# Windows: prebuilt/windows/ is committed to the repository. +# Run scripts/bootstrap_sdl_mixer_windows.ps1 once to (re)generate it. +# Linux: prebuilt/linux/ is built in-place on the Linux remote. +# Run scripts/bootstrap_sdl_mixer_linux.sh once after cloning. + +set(SDL_MIXER_PREBUILT_DIR "${CMAKE_SOURCE_DIR}/prebuilt/${PLATFORM}") + +if(SDL_LINK_TYPE STREQUAL "static") + set(SDL_MIXER_SEARCH_DIR "${SDL_MIXER_PREBUILT_DIR}/SDL2_mixer-static") +else() + set(SDL_MIXER_SEARCH_DIR "${SDL_MIXER_PREBUILT_DIR}/SDL2_mixer-dynamic") +endif() + +message(STATUS "Looking for SDL2_mixer in: ${SDL_MIXER_SEARCH_DIR}") + +find_package(SDL2_mixer REQUIRED CONFIG + PATHS "${SDL_MIXER_SEARCH_DIR}" + NO_DEFAULT_PATH +) + +if(SDL_LINK_TYPE STREQUAL "static") + set(SDL_MIXER_TARGET SDL2_mixer::SDL2_mixer-static) +else() + set(SDL_MIXER_TARGET SDL2_mixer::SDL2_mixer) +endif() + +message(STATUS "SDL_MIXER_TARGET resolved to: ${SDL_MIXER_TARGET}") + +if(SDL_LINK_TYPE STREQUAL "dynamic" AND WIN32) + add_custom_target(copy_sdl_mixer_dll ALL + COMMAND ${CMAKE_COMMAND} -E copy_if_different + $ + "${CMAKE_BINARY_DIR}/game/$" + COMMENT "Copying SDL2_mixer.dll to output directory" + ) +endif() + +if(SDL_LINK_TYPE STREQUAL "dynamic" AND UNIX AND NOT APPLE) + get_target_property(SDL2_MIXER_SO_LOCATION SDL2_mixer::SDL2_mixer LOCATION) + get_filename_component(SDL2_MIXER_LIB_DIR "${SDL2_MIXER_SO_LOCATION}" DIRECTORY) + message(STATUS "SDL2_mixer runtime library directory: ${SDL2_MIXER_LIB_DIR}") + list(APPEND SDL_LINUX_RPATH "${SDL2_MIXER_LIB_DIR}") + set(SDL_LINUX_RPATH "${SDL_LINUX_RPATH}" CACHE INTERNAL "") +endif() \ No newline at end of file diff --git a/engine/CMakeLists.txt b/engine/CMakeLists.txt index 81ce8d8..3f85ca2 100644 --- a/engine/CMakeLists.txt +++ b/engine/CMakeLists.txt @@ -7,8 +7,9 @@ target_include_directories(engine PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src ) -# SDL_TARGET is set by cmake/SDLSetup.cmake -target_link_libraries(engine PUBLIC ${SDL_TARGET}) +target_link_libraries(engine PUBLIC + ${SDL_TARGET} +) target_compile_definitions(engine PRIVATE $<$:SDL_STATIC_LIB> diff --git a/prebuilt/linux/SDL3-dynamic/lib/libSDL3.so b/prebuilt/linux/SDL3-dynamic/lib/libSDL3.so index d462326..4fd7ff3 120000 --- a/prebuilt/linux/SDL3-dynamic/lib/libSDL3.so +++ b/prebuilt/linux/SDL3-dynamic/lib/libSDL3.so @@ -1 +1 @@ -libSDL3.so.0.2 \ No newline at end of file +libSDL3.so.0 \ No newline at end of file diff --git a/prebuilt/linux/SDL3-dynamic/lib/libSDL3.so.0 b/prebuilt/linux/SDL3-dynamic/lib/libSDL3.so.0 index d78f628..d462326 120000 --- a/prebuilt/linux/SDL3-dynamic/lib/libSDL3.so.0 +++ b/prebuilt/linux/SDL3-dynamic/lib/libSDL3.so.0 @@ -1 +1 @@ -libSDL3.so.0.2.10 \ No newline at end of file +libSDL3.so.0.2 \ No newline at end of file diff --git a/scripts/bootstrap_sdl_mixer_linux.sh b/scripts/bootstrap_sdl_mixer_linux.sh new file mode 100644 index 0000000..50fae63 --- /dev/null +++ b/scripts/bootstrap_sdl_mixer_linux.sh @@ -0,0 +1,73 @@ +#!/usr/bin/env bash +# One-time bootstrap: builds SDL2_mixer from source and installs it into prebuilt/linux/. +# SDL3 must already be bootstrapped via bootstrap_sdl_linux.sh before running this. +# Run this once on the Linux remote after cloning. Re-run only when upgrading SDL2_mixer. +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +SDL_MIXER_VERSION="${1:-2.8.1}" +BUILD_TYPE="${2:-Release}" +BUILD_DIR="$PROJECT_ROOT/out/build/_sdl_mixer_bootstrap/linux" +PREBUILT_DIR="$PROJECT_ROOT/prebuilt/linux" +SDL_MIXER_SOURCE="$BUILD_DIR/SDL2_mixer-src" + +# Install build dependencies (Debian 12 bookworm) +echo "Checking build dependencies..." +sudo apt-get update -qq +sudo apt-get install -y --no-install-recommends \ + ninja-build cmake build-essential \ + gcc-12 g++-12 \ + libmpg123-dev libopusfile-dev libvorbis-dev libflac-dev + +# Download SDL2_mixer source if not already present +if [ ! -d "$SDL_MIXER_SOURCE" ]; then + echo "" + echo "=== Downloading SDL2_mixer $SDL_MIXER_VERSION ===" + mkdir -p "$BUILD_DIR" + curl -L "https://github.com/libsdl-org/SDL_mixer/releases/download/release-${SDL_MIXER_VERSION}/SDL2_mixer-${SDL_MIXER_VERSION}.tar.gz" \ + | tar -xz -C "$BUILD_DIR" + mv "$BUILD_DIR/SDL2_mixer-${SDL_MIXER_VERSION}" "$SDL_MIXER_SOURCE" +fi + +build_sdl_mixer() { + local LINK_TYPE="$1" + local SHARED="OFF" + local STATIC="OFF" + + if [ "$LINK_TYPE" = "dynamic" ]; then SHARED="ON"; else STATIC="ON"; fi + + local OUT_DIR="$PREBUILT_DIR/SDL2_mixer-$LINK_TYPE" + local BUILD_OUT="$BUILD_DIR/$LINK_TYPE" + + echo "" + echo "=== Building SDL2_mixer ($LINK_TYPE) for Linux ===" + + # Wipe any stale build directory to avoid corrupted cache issues + if [ -d "$BUILD_OUT" ]; then + echo "Removing stale build directory: $BUILD_OUT" + rm -rf "$BUILD_OUT" + fi + + cmake -S "$SDL_MIXER_SOURCE" -B "$BUILD_OUT" \ + -G "Ninja" \ + -DCMAKE_BUILD_TYPE="$BUILD_TYPE" \ + -DCMAKE_INSTALL_PREFIX="$OUT_DIR" \ + -DCMAKE_C_COMPILER=gcc-12 \ + -DCMAKE_CXX_COMPILER=g++-12 \ + -DSDL2MIXER_SHARED="$SHARED" \ + -DSDL2MIXER_STATIC="$STATIC" \ + -DSDL2MIXER_INSTALL=ON \ + -DSDL2MIXER_SAMPLES=OFF \ + -DSDL2MIXER_MIDI_FLUIDSYNTH=OFF \ + -DSDL2MIXER_WAVPACK=OFF \ + -DSDL3_DIR="$PREBUILT_DIR/SDL3-$LINK_TYPE/lib/cmake/SDL3" + + cmake --build "$BUILD_OUT" + cmake --install "$BUILD_OUT" + + echo "=== Done: $OUT_DIR ===" +} + +build_sdl_mixer "dynamic" +build_sdl_mixer "static" \ No newline at end of file diff --git a/scripts/bootstrap_sdl_mixer_windows.ps1 b/scripts/bootstrap_sdl_mixer_windows.ps1 new file mode 100644 index 0000000..5a9c30d --- /dev/null +++ b/scripts/bootstrap_sdl_mixer_windows.ps1 @@ -0,0 +1,66 @@ +# One-time bootstrap: builds SDL2_mixer from source and installs it into prebuilt/windows/. +# SDL3 must already be bootstrapped via bootstrap_sdl_windows.ps1 before running this. +# Run this once after cloning. Re-run only when upgrading SDL2_mixer. +param( + [string]$SdlMixerVersion = "2.8.1", + [string]$BuildType = "Release" +) + +$ProjectRoot = Resolve-Path "$PSScriptRoot\.." +$BuildDir = "$ProjectRoot\out\build\_sdl_mixer_bootstrap\windows" +$PrebuiltDir = "$ProjectRoot\prebuilt\windows" +$SdlMixerSource = "$BuildDir\SDL2_mixer-src" + +# Download SDL2_mixer source if not already present +if (-not (Test-Path $SdlMixerSource)) { + Write-Host "`n=== Downloading SDL2_mixer $SdlMixerVersion ===" -ForegroundColor Cyan + New-Item -ItemType Directory -Force -Path $BuildDir | Out-Null + $Archive = "$BuildDir\SDL2_mixer-$SdlMixerVersion.tar.gz" + Invoke-WebRequest -Uri "https://github.com/libsdl-org/SDL_mixer/releases/download/release-$SdlMixerVersion/SDL2_mixer-$SdlMixerVersion.tar.gz" ` + -OutFile $Archive + tar -xf $Archive -C $BuildDir + Rename-Item "$BuildDir\SDL2_mixer-$SdlMixerVersion" "SDL2_mixer-src" + Remove-Item $Archive +} + +function Build-SDLMixer { + param([string]$LinkType) + + $Shared = if ($LinkType -eq "dynamic") { "ON" } else { "OFF" } + $Static = if ($LinkType -eq "static") { "ON" } else { "OFF" } + $OutDir = "$PrebuiltDir\SDL2_mixer-$LinkType" + $BuildOut = "$BuildDir\$LinkType" + $Sdl3Dir = "$PrebuiltDir\SDL3-$LinkType\cmake" + + Write-Host "`n=== Building SDL2_mixer ($LinkType) for Windows ===" -ForegroundColor Cyan + + if (Test-Path $BuildOut) { + Write-Host "Removing stale build directory: $BuildOut" -ForegroundColor Yellow + Remove-Item -Recurse -Force $BuildOut + } + + cmake -S "$SdlMixerSource" -B "$BuildOut" ` + -G "Visual Studio 17 2022" ` + -A x64 ` + -DCMAKE_INSTALL_PREFIX="$OutDir" ` + -DSDL2MIXER_SHARED="$Shared" ` + -DSDL2MIXER_STATIC="$Static" ` + -DSDL2MIXER_INSTALL=ON ` + -DSDL2MIXER_SAMPLES=OFF ` + -DSDL2MIXER_MIDI_FLUIDSYNTH=OFF ` + -DSDL2MIXER_WAVPACK=OFF ` + -DSDL3_DIR="$Sdl3Dir" + + if ($LASTEXITCODE -ne 0) { Write-Error "CMake configure failed"; exit 1 } + + cmake --build "$BuildOut" --config "$BuildType" + if ($LASTEXITCODE -ne 0) { Write-Error "CMake build failed"; exit 1 } + + cmake --install "$BuildOut" --config "$BuildType" + if ($LASTEXITCODE -ne 0) { Write-Error "CMake install failed"; exit 1 } + + Write-Host "=== Done: $OutDir ===" -ForegroundColor Green +} + +Build-SDLMixer -LinkType "dynamic" +Build-SDLMixer -LinkType "static" \ No newline at end of file