sdl12-compat: Updated release workflow (#375)

From ca4b3f7d077128a6a7596c76931155a7a9ccf524 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Mon, 27 Oct 2025 09:30:43 -0700
Subject: [PATCH] Updated release workflow (#375)

Co-authored-by: Anonymous Maarten <anonymous.maarten@gmail.com>
---
 .github/actions/setup-ninja/action.yml |  62 +++++++++++++++
 .github/workflows/release.yml          |  83 +++++---------------
 CMakeLists.txt                         | 104 +++++--------------------
 build-scripts/build-release.py         |  20 +++--
 build-scripts/release-info.json        |  44 ++++++-----
 test/CMakeLists.txt                    |  98 +++++++++++++++++++++++
 6 files changed, 237 insertions(+), 174 deletions(-)
 create mode 100644 .github/actions/setup-ninja/action.yml
 create mode 100644 test/CMakeLists.txt

diff --git a/.github/actions/setup-ninja/action.yml b/.github/actions/setup-ninja/action.yml
new file mode 100644
index 000000000..a1d3ad983
--- /dev/null
+++ b/.github/actions/setup-ninja/action.yml
@@ -0,0 +1,62 @@
+name: 'Setup ninja'
+description: 'Download ninja and add it to the PATH environment variable'
+inputs:
+  version:
+    description: 'Ninja version'
+    default: '1.12.1'
+runs:
+  using: 'composite'
+  steps:
+    - name: 'Calculate variables'
+      id: calc
+      shell: sh
+      run: |
+        case "${{ runner.os }}-${{ runner.arch }}" in
+          "Linux-X86" | "Linux-X64")
+            archive="ninja-linux.zip"
+            ;;
+          "Linux-ARM64")
+            archive="ninja-linux-aarch64.zip"
+            ;;
+          "macOS-X86" | "macOS-X64" | "macOS-ARM64")
+            archive="ninja-mac.zip"
+            ;;
+          "Windows-X86" | "Windows-X64")
+            archive="ninja-win.zip"
+            ;;
+          "Windows-ARM64")
+            archive="ninja-winarm64.zip"
+            ;;
+          *)
+            echo "Unsupported ${{ runner.os }}-${{ runner.arch }}"
+            exit 1;
+            ;;
+        esac
+        echo "archive=${archive}" >> ${GITHUB_OUTPUT}
+        echo "cache-key=${archive}-${{ inputs.version }}-${{ runner.os }}-${{ runner.arch }}" >> ${GITHUB_OUTPUT}
+    - name: 'Restore cached ${{ steps.calc.outputs.archive }}'
+      id: cache-restore
+      uses: actions/cache/restore@v4
+      with:
+        path: '${{ runner.temp }}/${{ steps.calc.outputs.archive }}'
+        key: ${{ steps.calc.outputs.cache-key }}
+    - name: 'Download ninja ${{ inputs.version }} for ${{ runner.os }} (${{ runner.arch }})'
+      if: ${{ !steps.cache-restore.outputs.cache-hit || steps.cache-restore.outputs.cache-hit == 'false' }}
+      shell: pwsh
+      run: |
+        Invoke-WebRequest "https://github.com/ninja-build/ninja/releases/download/v${{ inputs.version }}/${{ steps.calc.outputs.archive }}" -OutFile "${{ runner.temp }}/${{ steps.calc.outputs.archive }}"
+    - name: 'Cache ${{ steps.calc.outputs.archive }}'
+      if: ${{ !steps.cache-restore.outputs.cache-hit || steps.cache-restore.outputs.cache-hit == 'false' }}
+      uses: actions/cache/save@v4
+      with:
+        path: '${{ runner.temp }}/${{ steps.calc.outputs.archive }}'
+        key: ${{ steps.calc.outputs.cache-key }}
+    - name: 'Extract ninja'
+      shell: pwsh
+      run: |
+        7z "-o${{ runner.temp }}/ninja-${{ inputs.version }}-${{ runner.arch }}" x "${{ runner.temp }}/${{ steps.calc.outputs.archive }}"
+    - name: 'Set output variables'
+      id: final
+      shell: pwsh
+      run: |
+        echo "${{ runner.temp }}/ninja-${{ inputs.version }}-${{ runner.arch }}" >> $env:GITHUB_PATH
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 889fbc02b..14e1d239c 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -24,12 +24,12 @@ jobs:
         with:
           python-version: '3.11'
       - name: 'Fetch build-release.py'
-        uses: actions/checkout@v4
+        uses: actions/checkout@v5
         with:
           ref: ${{ inputs.commit }}
           sparse-checkout: 'build-scripts/build-release.py'
       - name: 'Set up SDL sources'
-        uses: actions/checkout@v4
+        uses: actions/checkout@v5
         with:
           ref: ${{ inputs.commit }}
           path: 'SDL'
@@ -96,40 +96,18 @@ jobs:
         shell: bash
         run: |
           ${{ steps.tar.outputs.path }}/build-scripts/test-versioning.sh
-      - name: 'Fetch build-release.py'
-        uses: actions/checkout@v4
+      - name: 'Fetch setup-ninja action'
+        uses: actions/checkout@v5
         with:
           ref: ${{ inputs.commit }}
           sparse-checkout: |
-            build-scripts/build-release.py
             .github/actions/setup-ninja/action.yml
-      - name: 'Download dependencies'
-        id: deps
-        env:
-          GH_TOKEN: ${{ github.token }}
-        run: |
-          python build-scripts/build-release.py \
-            --actions download \
-            --commit ${{ inputs.commit }} \
-            --root "${{ steps.tar.outputs.path }}" \
-            --github \
-            --debug
-      - name: 'Install Linux dependencies'
-        run: |
-          sudo apt-get update -y
-          sudo apt-get install -y \
-            gnome-desktop-testing libasound2-dev libpulse-dev libaudio-dev libjack-dev libsndio-dev \
-            libusb-1.0-0-dev libx11-dev libxext-dev libxrandr-dev libxcursor-dev libxfixes-dev libxi-dev \
-            libxss-dev libwayland-dev libxkbcommon-dev libdrm-dev libgbm-dev libgl1-mesa-dev libgles2-mesa-dev \
-            libegl1-mesa-dev libdbus-1-dev libibus-1.0-dev libudev-dev fcitx-libs-dev
-      - name: 'Extract dependencies, build and install them'
-        id: deps-build
-        run: |
-          tar -C /tmp -v -x -f "${{ steps.deps.outputs.dep-path }}/SDL3-${{ steps.deps.outputs.dep-sdl-version }}.tar.gz"
-          cmake -S /tmp/SDL3-${{ steps.deps.outputs.dep-sdl-version }} -B /tmp/SDL-build -DSDL_UNIX_CONSOLE_BUILD=ON -DCMAKE_INSTALL_PREFIX=/tmp/deps-prefix
-          cmake --build /tmp/SDL-build
-          cmake --install /tmp/SDL-build
-          echo "path=/tmp/deps-prefix" >>$GITHUB_OUTPUT
+      - name: 'Setup sdl2-compat'
+        uses: libsdl-org/setup-sdl@main
+        with:
+          version: 3-latest
+          version-sdl2-compat: 2-latest
+          install-linux-dependencies: true
       - name: Set up ninja
         uses: ./.github/actions/setup-ninja
       - name: 'CMake (configure + build)'
@@ -137,8 +115,7 @@ jobs:
           cmake \
             -GNinja \
             -S ${{ steps.tar.outputs.path }} \
-            -B /tmp/build \
-            -DCMAKE_PREFIX_PATH="${{ steps.deps-build.outputs.path }}"
+            -B /tmp/build
           cmake --build /tmp/build --verbose
           # ctest --test-dir /tmp/build --no-tests=error --output-on-failure
 
@@ -153,7 +130,7 @@ jobs:
 #        with:
 #          python-version: '3.11'
 #      - name: 'Fetch build-release.py'
-#        uses: actions/checkout@v4
+#        uses: actions/checkout@v5
 #        with:
 #          ref: ${{ inputs.commit }}
 #          sparse-checkout: 'build-scripts/build-release.py'
@@ -201,7 +178,7 @@ jobs:
 #        with:
 #          python-version: '3.11'
 #      - name: 'Fetch build-release.py'
-#        uses: actions/checkout@v4
+#        uses: actions/checkout@v5
 #        with:
 #          ref: ${{ inputs.commit }}
 #          sparse-checkout: 'build-scripts/build-release.py'
@@ -343,7 +320,7 @@ jobs:
         with:
           python-version: '3.11'
       - name: 'Fetch build-release.py'
-        uses: actions/checkout@v4
+        uses: actions/checkout@v5
         with:
           ref: ${{ inputs.commit }}
           sparse-checkout: 'build-scripts/build-release.py'
@@ -384,7 +361,7 @@ jobs:
     runs-on: windows-latest
     steps:
       - name: 'Fetch .github/actions/setup-ninja/action.yml'
-        uses: actions/checkout@v4
+        uses: actions/checkout@v5
         with:
           ref: ${{ inputs.commit }}
           sparse-checkout: |
@@ -408,24 +385,6 @@ jobs:
           cd '${{ github.workspace }}/sources'
           unzip "${{ github.workspace }}/${{ needs.src.outputs.src-zip }}"
           echo "path=${{ github.workspace }}/sources/${{ needs.src.outputs.project }}-${{ needs.src.outputs.version }}" >>$env:GITHUB_OUTPUT
-      - name: 'Download dependencies'
-        id: deps
-        env:
-          GH_TOKEN: ${{ github.token }}
-        run: |
-          python build-scripts/build-release.py `
-            --actions download `
-            --commit ${{ inputs.commit }} `
-            --root "${{ steps.src.outputs.path }}" `
-            --github `
-            --debug
-      - name: 'Extract dependencies'
-        id: deps-extract
-        run: |
-          mkdir '${{ github.workspace }}/deps-vc'
-          cd '${{ github.workspace }}/deps-vc'
-          unzip "${{ steps.deps.outputs.dep-path }}/SDL3-devel-${{ steps.deps.outputs.dep-sdl-version }}-VC.zip"
-          echo "path=${{ github.workspace }}/deps-vc" >>$env:GITHUB_OUTPUT
       - name: 'Download MSVC binaries'
         uses: actions/download-artifact@v4
         with:
@@ -444,7 +403,7 @@ jobs:
           arch: x64_x86
       - name: 'CMake (configure + build + tests) x86'
         run: |
-          cmake -S "${{ steps.src.outputs.path }}/cmake/test"     `
+          cmake -S "${{ steps.src.outputs.path }}/test"           `
               -B build_x86                                        `
               -GNinja                                             `
               -DCMAKE_BUILD_TYPE=Debug                            `
@@ -452,7 +411,7 @@ jobs:
               -DTEST_SHARED=TRUE                                  `
               -DTEST_STATIC=FALSE                                 `
               -DCMAKE_SUPPRESS_REGENERATION=TRUE                  `
-              -DCMAKE_PREFIX_PATH="${{ steps.bin.outputs.path }};${{ steps.deps-extract.outputs.path }}"
+              -DCMAKE_PREFIX_PATH="${{ steps.bin.outputs.path }}"
           Start-Sleep -Seconds 2
           cmake --build build_x86 --config Release --verbose
       - name: 'Configure vcvars x64'
@@ -461,7 +420,7 @@ jobs:
           arch: x64
       - name: 'CMake (configure + build + tests) x64'
         run: |
-          cmake -S "${{ steps.src.outputs.path }}/cmake/test"     `
+          cmake -S "${{ steps.src.outputs.path }}/test"           `
               -B build_x64                                        `
               -GNinja                                             `
               -DCMAKE_BUILD_TYPE=Debug                            `
@@ -469,7 +428,7 @@ jobs:
               -DTEST_SHARED=TRUE                                  `
               -DTEST_STATIC=FALSE                                 `
               -DCMAKE_SUPPRESS_REGENERATION=TRUE                  `
-              -DCMAKE_PREFIX_PATH="${{ steps.bin.outputs.path }};${{ steps.deps-extract.outputs.path }}"
+              -DCMAKE_PREFIX_PATH="${{ steps.bin.outputs.path }}"
           Start-Sleep -Seconds 2
           cmake --build build_x64 --config Release --verbose
 #      - name: 'Configure vcvars arm64'
@@ -502,7 +461,7 @@ jobs:
 #        with:
 #          python-version: '3.11'
 #      - name: 'Fetch build-release.py'
-#        uses: actions/checkout@v4
+#        uses: actions/checkout@v5
 #        with:
 #          ref: ${{ inputs.commit }}
 #          sparse-checkout: 'build-scripts/build-release.py'
@@ -550,7 +509,7 @@ jobs:
 #        with:
 #          python-version: '3.11'
 #      - name: 'Fetch build-release.py'
-#        uses: actions/checkout@v4
+#        uses: actions/checkout@v5
 #        with:
 #          ref: ${{ inputs.commit }}
 #          sparse-checkout: 'build-scripts/build-release.py'
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6094ec958..c1299e662 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,7 +2,7 @@
 #        you can define SDL2_INCLUDE_DIR on the cmdline.  For example:
 #        cmake -DSDL2_INCLUDE_DIR=/opt/SDL2/include/SDL2 [other stuff]
 
-cmake_minimum_required(VERSION 3.0.0...4.0)
+cmake_minimum_required(VERSION 3.0.0...4.1)
 project(sdl12_compat VERSION 1.2.69 LANGUAGES C)
 
 option(SDL12TESTS "Enable to build SDL-1.2 test programs" ON)
@@ -22,8 +22,6 @@ include(CheckIncludeFile)
 include(CheckCCompilerFlag)
 include(GNUInstallDirs)
 
-set(CMAKE_SKIP_RPATH TRUE)
-
 if(APPLE)
   set(OSX_SRCS "src/SDL12_compat_objc.m")
   set_source_files_properties(${OSX_SRCS} PROPERTIES LANGUAGE C)
@@ -53,8 +51,11 @@ set(SDL12COMPAT_SRCS
   ${WIN32_SRCS}
 )
 add_library(SDL SHARED ${SDL12COMPAT_SRCS})
+add_library(SDL::SDL-shared ALIAS SDL)
+add_library(SDL::SDL ALIAS SDL)
 
-find_package(SDL2)
+find_package(SDL2 CONFIG)
+find_package(SDL2 MODULE)
 if(NOT SDL2_INCLUDE_DIRS)
   message(FATAL_ERROR "Could not find SDL2 headers")
 endif()
@@ -136,6 +137,7 @@ return 0; }" IS_X86)
     set_target_properties(SDL PROPERTIES COMPILE_FLAGS ${MSVC_FLAGS})
     set_target_properties(SDL PROPERTIES LINK_FLAGS "/NODEFAULTLIB")
     # Make sure /RTC1 is disabled: (from SDL2 CMake)
+    set_property(TARGET SDL PROPERTY MSVC_RUNTIME_CHECKS "")
     foreach(flag_var
       CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
       CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO)
@@ -156,90 +158,19 @@ elseif(WIN32)
 else()
     add_library(SDLmain STATIC src/SDLmain/dummy/SDL_dummy_main.c)
 endif()
-target_include_directories(SDLmain PRIVATE "include/SDL")
-
-if(SDL12TESTS)
-    if(NOT (WIN32 OR APPLE OR CYGWIN OR HAIKU OR BEOS))
-      find_library(MATH_LIBRARY m)
-    endif()
-
-    find_package(OpenGL COMPONENTS OpenGL)
-    if(OPENGL_FOUND)
-      set(HAVE_OPENGL_DEFINE "HAVE_OPENGL")
-      if(WIN32)
-        set(OPENGL_gl_LIBRARY "opengl32")
-        set(OPENGL_opengl_LIBRARY "opengl32")
-      elseif(APPLE)
-        set(OPENGL_gl_LIBRARY "-Wl,-framework,OpenGL")
-        set(OPENGL_opengl_LIBRARY "-Wl,-framework,OpenGL")
-      endif()
-    endif()
-
-    macro(test_program _NAME _SRCS)
-        add_executable(${_NAME} ${_SRCS})
-        target_include_directories(${_NAME} PRIVATE "include/SDL")
-        if(MINGW)
-          target_link_libraries(${_NAME} mingw32 SDLmain SDL)
-        else()
-          target_link_libraries(${_NAME} SDLmain SDL)
-        endif()
-        # Turn off MSVC's aggressive C runtime warnings for the old test programs.
-        if(MSVC)
-          set_target_properties(${_NAME} PROPERTIES COMPILE_DEFINITIONS "${HAVE_OPENGL_DEFINE};_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE")
-        elseif(APPLE)
-          set_target_properties(${_NAME} PROPERTIES COMPILE_DEFINITIONS "${HAVE_OPENGL_DEFINE};GL_SILENCE_DEPRECATION=1")
-          target_link_libraries(${_NAME} "-Wl,-framework,Cocoa")
-        else()
-          set_target_properties(${_NAME} PROPERTIES COMPILE_DEFINITIONS "${HAVE_OPENGL_DEFINE}")
-        endif()
-        if(MATH_LIBRARY)
-          target_link_libraries(${_NAME} ${MATH_LIBRARY})
-        endif()
-    endmacro()
-
-    test_program(checkkeys "test/checkkeys.c")
-    test_program(graywin "test/graywin.c")
-    test_program(loopwave "test/loopwave.c")
-    test_program(testalpha "test/testalpha.c")
-    test_program(testbitmap "test/testbitmap.c")
-    test_program(testblitspeed "test/testblitspeed.c")
-    test_program(testcdrom "test/testcdrom.c")
-    test_program(testcursor "test/testcursor.c")
-    test_program(testerror "test/testerror.c")
-    test_program(testfile "test/testfile.c")
-    test_program(testgamma "test/testgamma.c")
-    test_program(testthread "test/testthread.c")
-    test_program(testiconv "test/testiconv.c")
-    test_program(testjoystick "test/testjoystick.c")
-    test_program(testkeys "test/testkeys.c")
-    test_program(testloadso "test/testloadso.c")
-    test_program(testlock "test/testlock.c")
-    test_program(testoverlay "test/testoverlay.c")
-    test_program(testoverlay2 "test/testoverlay2.c")
-    test_program(testpalette "test/testpalette.c")
-    test_program(testplatform "test/testplatform.c")
-    test_program(testsem "test/testsem.c")
-    test_program(testsprite "test/testsprite.c")
-    test_program(testtimer "test/testtimer.c")
-    test_program(testver "test/testver.c")
-    test_program(testvidinfo "test/testvidinfo.c")
-    test_program(testwin "test/testwin.c")
-    test_program(testwm "test/testwm.c")
-    test_program(threadwin "test/threadwin.c")
-    test_program(torturethread "test/torturethread.c")
-    test_program(testdyngl "test/testdyngl.c")
-    test_program(testgl "test/testgl.c")
-    if(OPENGL_FOUND)
-      if(CMAKE_VERSION VERSION_LESS 3.10 OR NOT OPENGL_opengl_LIBRARY)
-        target_link_libraries(testgl ${OPENGL_gl_LIBRARY})
-      else()
-        target_link_libraries(testgl ${OPENGL_opengl_LIBRARY})
-      endif()
+add_library(SDL::SDLmain ALIAS SDLmain)
+target_include_directories(SDLmain PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/SDL>")
+target_include_directories(SDLmain PUBLIC "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/SDL>")
+if(MINGW OR CYGWIN)
+    if(CMAKE_SIZEOF_VOID_P EQUAL 4)
+        target_link_libraries(SDLmain PUBLIC "$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:-Wl,--undefined=_WinMain@16>")
+    else()
+        target_link_libraries(SDLmain PUBLIC "$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:-Wl,--undefined=WinMain>")
     endif()
+endif()
 
-    foreach(fname "icon.bmp" "moose.dat" "picture.xbm" "sail.bmp" "sample.bmp" "sample.wav" "utf8.txt")
-        file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/test/${fname}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")
-    endforeach(fname)
+if(SDL12TESTS)
+    add_subdirectory(test)
 endif()
 
 install(TARGETS SDL SDLmain
@@ -317,6 +248,7 @@ endif()
 
 if(STATICDEVEL AND SDL12DEVEL)
   add_library(SDL-static STATIC ${SDL12COMPAT_SRCS})
+  add_library(SDL::SDL-static ALIAS SDL-static)
   target_include_directories(SDL-static PRIVATE ${SDL2_INCLUDE_DIRS})
   set_target_properties(SDL-static PROPERTIES COMPILE_DEFINITIONS "_REENTRANT")
   target_link_libraries(SDL-static PRIVATE ${CMAKE_DL_LIBS})
diff --git a/build-scripts/build-release.py b/build-scripts/build-release.py
index f3faa06c3..d7e7028ec 100755
--- a/build-scripts/build-release.py
+++ b/build-scripts/build-release.py
@@ -542,6 +542,7 @@ def __init__(self, name: str, ints: tuple[int, ...]):
     def __repr__(self) -> str:
         return f"<{self.name} ({'.'.join(str(v) for v in self.ints)})>"
 
+ANDROID_ABI_EXTRA_LINK_OPTIONS = {}
 
 class Releaser:
     def __init__(self, release_info: dict, commit: str, revision: str, root: Path, dist_path: Path, section_printer: SectionPrinter, executer: Executer, cmake_generator: str, deps_path: Path, overwrite: bool, github: bool, fast: bool):
@@ -1013,6 +1014,7 @@ def create_android_archives(self, android_api: int, android_home: Path, android_
         android_devel_file_tree = ArchiveFileTree()
 
         for android_abi in android_abis:
+            extra_link_options = ANDROID_ABI_EXTRA_LINK_OPTIONS.get(android_abi, "")
             with self.section_printer.group(f"Building for Android {android_api} {android_abi}"):
                 build_dir = self.root / "build-android" / f"{android_abi}-build"
                 install_dir = self.root / "install-android" / f"{android_abi}-install"
@@ -1023,8 +1025,11 @@ def create_android_archives(self, android_api: int, android_home: Path, android_
                     "cmake",
                     "-S", str(self.root),
                     "-B", str(build_dir),
-                    f'''-DCMAKE_C_FLAGS="-ffile-prefix-map={self.root}=/src/{self.project}"''',
-                    f'''-DCMAKE_CXX_FLAGS="-ffile-prefix-map={self.root}=/src/{self.project}"''',
+                    # NDK 21e does not support -ffile-prefix-map
+                    # f'''-DCMAKE_C_FLAGS="-ffile-prefix-map={self.root}=/src/{self.project}"''',
+                    # f'''-DCMAKE_CXX_FLAGS="-ffile-prefix-map={self.root}=/src/{self.project}"''',
+                    f"-DCMAKE_EXE_LINKER_FLAGS={extra_link_options}",
+                    f"-DCMAKE_SHARED_LINKER_FLAGS={extra_link_options}",
                     f"-DCMAKE_TOOLCHAIN_FILE={cmake_toolchain_file}",
                     f"-DCMAKE_PREFIX_PATH={str(android_deps_path)}",
                     f"-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=BOTH",
@@ -1179,7 +1184,7 @@ def build_msvc(self):
         with self.section_printer.group("Create SDL VC development zip"):
             self._build_msvc_devel()
 
-    def _build_msvc_msbuild(self, arch_platform: VsArchPlatformConfig, vs: VisualStudio):
+    def _copy_dep_files(self, arch_platform: VsArchPlatformConfig):
         platform_context = self.get_context(arch_platform.extra_context())
         for dep, depinfo in self.release_info["msvc"].get("dependencies", {}).items():
             msvc_zip = self.deps_path / glob.glob(depinfo["artifact"], root_dir=self.deps_path)[0]
@@ -1207,6 +1212,9 @@ def _build_msvc_msbuild(self, arch_platform: VsArchPlatformConfig, vs: VisualStu
                             dst.parent.mkdir(exist_ok=True, parents=True)
                             dst.write_bytes(zip_data)
 
+    def _build_msvc_msbuild(self, arch_platform: VsArchPlatformConfig, vs: VisualStudio):
+        self._copy_dep_files(arch_platform)
+
         prebuilt_paths = set(self.root / full_prebuilt_path for prebuilt_path in self.release_info["msvc"]["msbuild"].get("prebuilt", []) for full_prebuilt_path in glob.glob(configure_text(prebuilt_path, context=platform_context), root_dir=self.root))
         msbuild_paths = set(self.root / configure_text(f, context=platform_context) for file_mapping in (self.release_info["msvc"]["msbuild"]["files-lib"], self.release_info["msvc"]["msbuild"]["files-devel"]) for files_list in file_mapping.values() for f in files_list)
         assert prebuilt_paths.issubset(msbuild_paths), f"msvc.msbuild.prebuilt must be a subset of (msvc.msbuild.files-lib, msvc.msbuild.files-devel)"
@@ -1276,6 +1284,8 @@ def _build_msvc_cmake(self, arch_platform: VsArchPlatformConfig, dep_roots: list
             "PLATFORM": arch_platform.platform,
         }
 
+        self._copy_dep_files(arch_platform)
+
         built_paths = set(install_path / configure_text(f, context=platform_context) for file_mapping in (self.release_info["msvc"]["cmake"]["files-lib"], self.release_info["msvc"]["cmake"]["files-devel"]) for files_list in file_mapping.values() for f in files_list)
         logger.info("CMake builds these files, to be included in the package: %s", built_paths)
         if not self.fast:
@@ -1512,7 +1522,7 @@ def main(argv=None) -> int:
         if args.android_home is None or not Path(args.android_home).is_dir():
             parser.error("Invalid $ANDROID_HOME or --android-home: must be a directory containing the Android SDK")
         if args.android_ndk_home is None or not Path(args.android_ndk_home).is_dir():
-            parser.error("Invalid $ANDROID_NDK_HOME or --android_ndk_home: must be a directory containing the Android NDK")
+            parser.error("Invalid $ANDROID_NDK_HOME or --android-ndk-home: must be a directory containing the Android NDK")
         if args.android_api is None:
             with section_printer.group("Detect Android APIS"):
                 args.android_api = releaser._detect_android_api(android_home=args.android_home)
@@ -1530,7 +1540,7 @@ def main(argv=None) -> int:
             parser.error("Invalid --android-api, and/or could not be detected")
         android_api_path = Path(args.android_home) / f"platforms/{args.android_api.name}"
         if not android_api_path.is_dir():
-            parser.error(f"Android API directory does not exist ({android_api_path})")
+            logger.warning(f"Android API directory does not exist ({android_api_path})")
         with section_printer.group("Android arguments"):
             print(f"android_home     = {args.android_home}")
             print(f"android_ndk_home = {args.android_ndk_home}")
diff --git a/build-scripts/release-info.json b/build-scripts/release-info.json
index 33f531ac8..ef6b9c60a 100644
--- a/build-scripts/release-info.json
+++ b/build-scripts/release-info.json
@@ -2,13 +2,9 @@
   "name": "sdl12-compat",
   "remote": "libsdl-org/sdl12-compat",
   "dependencies": {
-    "SDL2": {
+    "sdl2-compat": {
       "startswith": "2.",
-      "repo": "libsdl-org/SDL"
-    },
-    "SDL3": {
-      "startswith": "3.",
-      "repo": "libsdl-org/SDL"
+      "repo": "libsdl-org/sdl2-compat"
     }
   },
   "version": {
@@ -20,7 +16,7 @@
   "source": {
     "checks": [
       "src/SDL12_compat.c",
-      "include/SDL/SDL_pixels.h",
+      "include/SDL/SDL.h",
       "test/testsprite.c"
     ]
   },
@@ -40,19 +36,12 @@
       ],
       "files-lib": {
         "": [
-          "bin/SDL.dll",
-          "bin/SDL2.dll",
-          "bin/SDL3.dll"
+          "bin/SDL.dll"
         ]
       },
       "files-devel": {
         "lib/@<@ARCH@>@": [
           "bin/SDL.dll",
-          "bin/SDL2.dll",
-          "bin/SDL3.dll",
-          "bin/SDL.pdb",
-          "bin/SDL2.pdb",
-          "bin/SDL3.pdb",
           "lib/SDL.lib",
           "lib/SDLmain.lib"
         ]
@@ -62,7 +51,9 @@
       "": [
         "build-scripts/pkg-support/msvc/@<@ARCH@>@/INSTALL.md.in:INSTALL.md",
         "LICENSE.txt",
-        "build-scripts/pkg-support/msvc/README.md"
+        "build-scripts/pkg-support/msvc/README.md",
+        "@<@ARCH@>@/SDL2.dll",
+        "@<@ARCH@>@/SDL3.dll"
       ]
     },
     "files-devel": {
@@ -73,14 +64,25 @@
       ],
       "include": [
         "include/SDL/*"
+      ],
+      "lib/@<@ARCH@>@": [
+        "@<@ARCH@>@/SDL2.dll",
+        "@<@ARCH@>@/SDL3.dll"
       ]
     },
     "dependencies": {
-      "SDL2": {
-        "artifact": "SDL2-devel-*-VC.zip"
-      },
-      "SDL3": {
-        "artifact": "SDL3-devel-*-VC.zip"
+      "sdl2-compat": {
+        "artifact": "sdl2-compat-devel-2.??.??-VC.zip",
+        "copy": [
+          {
+            "src": "lib/@<@ARCH@>@/SDL3.dll",
+            "dst": "@<@ARCH@>@"
+          },
+          {
+            "src": "lib/@<@ARCH@>@/SDL2.dll",
+            "dst": "@<@ARCH@>@"
+          }
+        ]
       }
     }
   }
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
new file mode 100644
index 000000000..bff2bf2a8
--- /dev/null
+++ b/test/CMakeLists.txt
@@ -0,0 +1,98 @@
+cmake_minimum_required(VERSION 3.0.0...4.0)
+project(sdl12_compat_tests C)
+
+if(NOT TARGET SDL::SDL)
+    find_package(SDL REQUIRED)
+endif()
+if(NOT TARGET SDL::SDLmain)
+    add_library(SDL::SDLmain STATIC IMPORTED)
+    if(SDLMAIN_LIBRARY)
+        message("SDLMAIN_LIBRARY=${SDLMAIN_LIBRARY}")
+        set_property(TARGET SDL::SDLmain PROPERTY IMPORTED_LOCATION "${SDLMAIN_LIBRARY}")
+    endif()
+    if(MINGW OR CYGWIN)
+        if(CMAKE_SIZEOF_VOID_P EQUAL 4)
+            set_property(TARGET SDL::SDLmain APPEND INTERFACE_LINK_LIBRARIES "$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:-Wl,--undefined=_WinMain@16>")
+        else()
+            set_property(TARGET SDL::SDLmain APPEND INTERFACE_LINK_LIBRARIES "$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:-Wl,--undefined=WinMain>")
+        endif()
+    endif()
+endif()
+
+if(NOT (WIN32 OR APPLE OR CYGWIN OR HAIKU OR BEOS))
+    find_library(MATH_LIBRARY m)
+endif()
+
+find_package(OpenGL COMPONENTS OpenGL)
+if(OPENGL_FOUND)
+    set(HAVE_OPENGL_DEFINE "HAVE_OPENGL")
+    if(WIN32)
+        set(OPENGL_gl_LIBRARY "opengl32")
+        set(OPENGL_opengl_LIBRARY "opengl32")
+    elseif(APPLE)
+        set(OPENGL_gl_LIBRARY "-Wl,-framework,OpenGL")
+        set(OPENGL_opengl_LIBRARY "-Wl,-framework,OpenGL")
+    endif()
+endif()
+
+macro(test_program _NAME _SRCS)
+    add_executable(${_NAME} ${_SRCS})
+    target_include_directories(${_NAME} PRIVATE "include/SDL")
+    target_link_libraries(${_NAME} PRIVATE SDL::SDLmain SDL::SDL)
+    # Turn off MSVC's aggressive C runtime warnings for the old test programs.
+    if(MSVC)
+        set_target_properties(${_NAME} PROPERTIES COMPILE_DEFINITIONS "${HAVE_OPENGL_DEFINE};_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE")
+    elseif(APPLE)
+        set_target_properties(${_NAME} PROPERTIES COMPILE_DEFINITIONS "${HAVE_OPENGL_DEFINE};GL_SILENCE_DEPRECATION=1")
+        target_link_libraries(${_NAME} PRIVATE "-Wl,-framework,Cocoa")
+    else()
+        set_target_properties(${_NAME} PROPERTIES COMPILE_DEFINITIONS "${HAVE_OPENGL_DEFINE}")
+    endif()
+    if(MATH_LIBRARY)
+        target_link_libraries(${_NAME} PRIVATE ${MATH_LIBRARY})
+    endif()
+endmacro()
+
+test_program(checkkeys "checkkeys.c")
+test_program(graywin "graywin.c")
+test_program(loopwave "loopwave.c")
+test_program(testalpha "testalpha.c")
+test_program(testbitmap "testbitmap.c")
+test_program(testblitspeed "testblitspeed.c")
+test_program(testcdrom "testcdrom.c")
+test_program(testcursor "testcursor.c")
+test_program(testerror "testerror.c")
+test_program(testfile "testfile.c")
+test_program(testgamma "testgamma.c")
+test_program(testthread "testthread.c")
+test_program(testiconv "testiconv.c")
+test_program(testjoystick "testjoystick.c")
+test_program(testkeys "testkeys.c")
+test_program(testloadso "testloadso.c")
+test_program(testlock "testlock.c")
+test_program(testoverlay "testoverlay.c")
+test_program(testoverlay2 "testoverlay2.c")
+test_program(testpalette "testpalette.c")
+test_program(testplatform "testplatform.c")
+test_program(testsem "testsem.c")
+test_program(testsprite "testsprite.c")
+test_program(testtimer "testtimer.c")
+test_program(testver "testver.c")
+test_program(testvidinfo "testvidinfo.c")
+test_program(testwin "testwin.c")
+test_program(testwm "testwm.c")
+test_program(threadwin "threadwin.c")
+test_program(torturethread "torturethread.c")
+test_program(testdyngl "testdyngl.c")
+test_program(testgl "testgl.c")
+if(OPENGL_FOUND)
+    if(CMAKE_VERSION VERSION_LESS 3.10 OR NOT OPENGL_opengl_LIBRARY)
+        target_link_libraries(testgl PRIVATE ${OPENGL_gl_LIBRARY})
+    else()
+        target_link_libraries(testgl PRIVATE ${OPENGL_opengl_LIBRARY})
+    endif()
+endif()
+
+foreach(fname "icon.bmp" "moose.dat" "picture.xbm" "sail.bmp" "sample.bmp" "sample.wav" "utf8.txt")
+    file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/${fname}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")
+endforeach(fname)