sdl2-compat: cmake: Make install prefix of sdl2_config more compatible with SDL2

From c10e593f231f1ce948a5fbca9f308aa64611f081 Mon Sep 17 00:00:00 2001
From: Anonymous Maarten <[EMAIL REDACTED]>
Date: Sun, 27 Nov 2022 03:00:36 +0100
Subject: [PATCH] cmake: Make install prefix of sdl2_config more compatible
 with SDL2

---
 CMakeLists.txt                    | 669 ++++++++++++++++++------------
 SDL2Config.cmake.in               |  62 +++
 cmake/modules/FindSDL3.cmake      | 392 -----------------
 include/SDL2/SDL_revision.h.cmake |   6 +-
 sdl2.m4                           | 214 ++++++++++
 5 files changed, 673 insertions(+), 670 deletions(-)
 create mode 100644 SDL2Config.cmake.in
 delete mode 100644 cmake/modules/FindSDL3.cmake
 create mode 100644 sdl2.m4

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 975074f..26da7ce 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,31 +1,65 @@
-# NOTE:  If you installed SDL2 at an unusual place and FindSDL2 fails,
-#        you can define SDL2_INCLUDE_DIR on the cmdline.  For example:
-#        cmake -DSDL2_INCLUDE_DIR=/opt/SDL2/include/SDL2 [other stuff]
+# NOTE:  If you installed SDL3 at an unusual place and SDL3Config fails,
+#        you can define SDL3_INCLUDE_DIRS on the cmdline.  For example:
+#        cmake -DSDL3_INCLUDE_DIRS="/opt/SDL3/include;/opt/SDL3/include/SDL3"
 
 cmake_minimum_required(VERSION 3.0.0)
 project(sdl2_compat
         VERSION 2.90.0
         LANGUAGES C)
 
-option(SDL2TESTS "Enable to build SDL2 test programs" ON)
-option(SDL2DEVEL "Enable installing SDL2 development headers" ON)
-option(STATICDEVEL "Enable installing static link library" OFF)
+option(SDL2COMPAT_TESTS "Enable to build SDL2 test programs" ON)
+option(SDL2COMPAT_DEVEL "Enable installing SDL2 development headers" ON)
+option(SDL2COMPAT_STATICDEVEL "Enable installing static link library" OFF)
+option(SDL2COMPAT_WERROR "Treat warnings as errors" ON)
+set(SDL2COMPAT_VENDOR_INFO "" CACHE STRING "Vendor name and/or version to add to SDL_REVISION")
+#FIXME: should SDL2-compat modify vendor_info/revision information?
 
-if(STATICDEVEL AND NOT (CMAKE_SYSTEM_NAME MATCHES "Linux"))
+if(SDL2COMPAT_STATICDEVEL AND NOT (CMAKE_SYSTEM_NAME MATCHES "Linux"))
   message(FATAL_ERROR "Static builds are only supported on Linux.")
 endif()
 
-list(APPEND CMAKE_MODULE_PATH
-    "${CMAKE_CURRENT_LIST_DIR}/cmake/modules"
-)
-
 include(CheckCSourceCompiles)
 include(CheckIncludeFile)
 include(CheckCCompilerFlag)
+include(CMakePackageConfigHelpers)
 include(GNUInstallDirs)
 
 set(CMAKE_SKIP_RPATH TRUE)
 
+find_package(SDL3)
+if(NOT SDL3_INCLUDE_DIRS)
+  find_path(SDL3_INCLUDE_DIRS
+    NAMES "SDL3/SDL.h"
+  )
+endif()
+
+find_package(Git)
+if(Git_FOUND)
+  execute_process(COMMAND
+      "${GIT_EXECUTABLE}" describe --always --tags --long
+      WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
+      RESULT_VARIABLE GIT_REVISION_STATUS
+      OUTPUT_VARIABLE GIT_REVISION
+      ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
+else()
+  set(GIT_REVISION_STATUS 1)
+  set(GIT_REVISION "")
+endif()
+
+if(GIT_REVISION_STATUS EQUAL 0)
+  if(GIT_REVISION MATCHES "^[0-9a-f]+$")
+    # Just a truncated sha1, so prefix it with the version number
+    set(SDL_REVISION "SDL-${sdl2_compat_VERSION}-g${GIT_REVISION}")
+  else()
+    # e.g. release-2.24.0-542-g96361fc47
+    set(SDL_REVISION "SDL-${GIT_REVISION}")
+  endif()
+else()
+  set(SDL_REVISION "SDL-${sdl2_compat_VERSION}-no-vcs")
+endif()
+
+configure_file(include/SDL2/SDL_revision.h.cmake include/SDL2/SDL_revision.h @ONLY)
+
 if(APPLE)
   set(OSX_SRCS "src/sdl2_compat_objc.m")
   set_source_files_properties(${OSX_SRCS} PROPERTIES LANGUAGE C)
@@ -36,7 +70,8 @@ if(APPLE)
 #  # higher version.
 #  set(DYLIB_COMPAT_VERSION 12.0.0 CACHE STRING "library compatibility version")
 #  set(DYLIB_CURRENT_VERSION 12.61.0 CACHE STRING "library current version")
-  include_directories("/opt/X11/include")  # hack.
+  find_package(X11)
+  include_directories("${X11_INCLUDE_DIR}")
   if(CMAKE_VERSION VERSION_LESS 3.9)
   else()
     cmake_policy(SET CMP0068 NEW)  # on macOS, don't let RPATH affect install_name.
@@ -52,24 +87,32 @@ set(SDL2COMPAT_SRCS
   ${OSX_SRCS}
   ${WIN32_SRCS}
 )
-add_library(SDL SHARED ${SDL2COMPAT_SRCS})
-
-find_package(SDL3)
-if(NOT SDL3_INCLUDE_DIRS)
-  message(FATAL_ERROR "Could not find SDL3 headers")
-endif()
-target_include_directories(SDL PRIVATE ${SDL3_INCLUDE_DIRS})
+add_library(SDL2 SHARED ${SDL2COMPAT_SRCS})
+add_library(SDL2::SDL2 ALIAS SDL2)
+target_include_directories(SDL2
+  PRIVATE
+    ${SDL3_INCLUDE_DIRS}
+  INTERFACE
+    "$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>"
+    "$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include/SDL2>"
+    "$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include>"
+    "$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include/SDL2>"
+    "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
+    "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/SDL2>"
+)
 
 set(EXTRA_CFLAGS )
-if (CMAKE_C_COMPILER_ID MATCHES "Clang|GNU")
+if(CMAKE_C_COMPILER_ID MATCHES "Clang|GNU")
   set(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Wall")
   check_c_compiler_flag(-Wdeclaration-after-statement HAVE_WDECLARATION_AFTER_STATEMENT)
   if(HAVE_WDECLARATION_AFTER_STATEMENT)
     set(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Wdeclaration-after-statement")
   endif()
-  check_c_compiler_flag(-Werror=declaration-after-statement HAVE_WERROR_DECLARATION_AFTER_STATEMENT)
-  if(HAVE_WERROR_DECLARATION_AFTER_STATEMENT)
-    set(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Werror=declaration-after-statement")
+  if(SDL2COMPAT_WERROR)
+    check_c_compiler_flag(-Werror=declaration-after-statement HAVE_WERROR_DECLARATION_AFTER_STATEMENT)
+    if(HAVE_WERROR_DECLARATION_AFTER_STATEMENT)
+      set(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Werror=declaration-after-statement")
+    endif()
   endif()
 endif()
 
@@ -82,270 +125,360 @@ endif()
 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
 string(STRIP "${CMAKE_C_FLAGS}" CMAKE_C_FLAGS)
 
+set_target_properties(SDL2 PROPERTIES DEFINE_SYMBOL "DLL_EXPORT")
 if(UNIX AND NOT APPLE)
-    set_target_properties(SDL PROPERTIES COMPILE_DEFINITIONS "_REENTRANT")
-    target_link_libraries(SDL PRIVATE ${CMAKE_DL_LIBS})
+  target_compile_definitions(SDL2 PRIVATE "_REENTRANT")
+  target_link_libraries(SDL2 PRIVATE ${CMAKE_DL_LIBS})
 endif()
 if(APPLE)
-    # !!! FIXME: check OUTPUT_NAME value, and do we need AppKit now? I assume that was for SDL_main code in 1.2.
-    set_target_properties(SDL PROPERTIES COMPILE_DEFINITIONS "_THREAD_SAFE")
-    set_target_properties(SDL PROPERTIES LINK_FLAGS
-            "-Wl,-compatibility_version,${DYLIB_COMPAT_VERSION} -Wl,-current_version,${DYLIB_CURRENT_VERSION}")
-    #target_link_libraries(SDL PRIVATE "-framework AppKit")
-    set_target_properties(SDL PROPERTIES
-        OUTPUT_NAME "SDL2-2.0.0"
-    )
+  # !!! FIXME: check OUTPUT_NAME value, and do we need AppKit now? I assume that was for SDL_main code in 1.2.
+  set_target_properties(SDL2 PROPERTIES COMPILE_DEFINITIONS "_THREAD_SAFE")
+  target_link_libraries(SDL2 PRIVATE
+    "-Wl,-compatibility_version,${DYLIB_COMPAT_VERSION}"
+    "-Wl,-current_version,${DYLIB_CURRENT_VERSION}"
+    # "-Wl,-framework,AppKit"
+  )
+  set_target_properties(SDL2 PROPERTIES
+      OUTPUT_NAME "SDL2-2.0.0"
+  )
 elseif(UNIX AND NOT ANDROID)
-    # !!! FIXME: check OUTPUT_NAME value
-    set_target_properties(SDL PROPERTIES
-        VERSION "${PROJECT_VERSION}"
-        SOVERSION "0"
-        OUTPUT_NAME "SDL2-2.0")
+  # !!! FIXME: check OUTPUT_NAME value
+  set_target_properties(SDL2 PROPERTIES
+    VERSION "${PROJECT_VERSION}"
+    SOVERSION "0"
+    OUTPUT_NAME "SDL2-2.0"
+  )
 elseif(WIN32)
-    # avoid DLL having 'lib' prefix with MinGW
-    set(CMAKE_SHARED_LIBRARY_PREFIX "")
-    set_target_properties(SDL PROPERTIES COMPILE_DEFINITIONS "DLL_EXPORT")
-    set_target_properties(SDL PROPERTIES
-        VERSION "${PROJECT_VERSION}"
-        SOVERSION "0"
-        OUTPUT_NAME "SDL2")
+  # avoid DLL having 'lib' prefix with MinGW
+  set_target_properties(SDL2 PROPERTIES
+    VERSION "${PROJECT_VERSION}"
+    SOVERSION "0"
+    OUTPUT_NAME "SDL2"
+    SHARED_LIBRARY_PREFIX ""
+  )
 elseif(OS2)
-    set_target_properties(SDL PROPERTIES COMPILE_DEFINITIONS "BUILD_SDL") # for DECLSPEC
-    set_target_properties(SDL PROPERTIES
-        VERSION "${PROJECT_VERSION}"
-        SOVERSION "0"
-        OUTPUT_NAME "SDL2")
+  set_target_properties(SDL2 PROPERTIES
+    VERSION "${PROJECT_VERSION}"
+    SOVERSION "0"
+    OUTPUT_NAME "SDL2"
+  )
 else()
-    set_target_properties(SDL PROPERTIES
-        VERSION "${PROJECT_VERSION}"
-        SOVERSION "0"
-        OUTPUT_NAME "SDL2")
+  set_target_properties(SDL2 PROPERTIES
+    VERSION "${PROJECT_VERSION}"
+    SOVERSION "0"
+    OUTPUT_NAME "SDL2"
+  )
 endif()
 
 if(MINGW)
-    set_target_properties(SDL PROPERTIES LINK_FLAGS "-nostdlib")
-    target_link_libraries(SDL PRIVATE "-static-libgcc -lgcc") # libgcc is needed for 32 bit (x86) builds
+  set_target_properties(SDL2 PROPERTIES LINK_FLAGS "-nostdlib")
+  target_link_libraries(SDL2 PRIVATE -static-libgcc -lgcc) # libgcc is needed for 32 bit (x86) builds
 endif()
 if(MSVC)
-    # Don't try to link with the default set of libraries.
-    set(MSVC_FLAGS "/GS-")
-    check_c_source_compiles("int main(void) {
+  # Don't try to link with the default set of libraries.
+  set(MSVC_FLAGS "/GS-")
+  check_c_source_compiles("int main(void) {
 #ifndef _M_IX86
 #error not x86
 #endif
 return 0; }" IS_X86)
-    if(IS_X86)  # don't emit SSE2 in x86 builds
-      set(MSVC_FLAGS "${MSVC_FLAGS} /arch:SSE")
-    endif()
-    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)
-    foreach(flag_var
-      CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
-      CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO)
-      string(REGEX REPLACE "/RTC(su|[1su])" "" ${flag_var} "${${flag_var}}")
-    endforeach(flag_var)
+  if(IS_X86)  # don't emit SSE2 in x86 builds
+    set(MSVC_FLAGS "${MSVC_FLAGS} /arch:SSE")
+  endif()
+  set_target_properties(SDL2 PROPERTIES COMPILE_FLAGS ${MSVC_FLAGS})
+  set_target_properties(SDL2 PROPERTIES LINK_FLAGS "/NODEFAULTLIB")
+  # Make sure /RTC1 is disabled: (from SDL2 CMake)
+  foreach(flag_var
+    CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
+    CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO)
+    string(REGEX REPLACE "/RTC(su|[1su])" "" ${flag_var} "${${flag_var}}")
+  endforeach(flag_var)
 endif()
 
 # !!! FIXME: what needs to be done for sdl2-compat? Look into this.
-## SDLmain library...
+## SDL2main library...
 #if(APPLE)
-#    add_library(SDLmain STATIC src/SDLmain/macosx/SDLMain.m)
+#    add_library(SDL2main STATIC src/SDLmain/macosx/SDLMain.m)
 #    set_source_files_properties(src/SDLmain/macosx/SDLMain.m PROPERTIES LANGUAGE C)
 #elseif(WIN32)
-#    add_library(SDLmain STATIC src/SDLmain/win32/SDL_win32_main.c)
-#    set_target_properties(SDLmain PROPERTIES COMPILE_DEFINITIONS "_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE")  # !!! FIXME: don't use C runtime? We fixed this in SDL2.
+#    add_library(SDL2main STATIC src/SDLmain/win32/SDL_win32_main.c)
+#    set_target_properties(SDL2main PROPERTIES COMPILE_DEFINITIONS "_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE")  # !!! FIXME: don't use C runtime? We fixed this in SDL2.
 #else()
-    add_library(SDLmain STATIC src/SDLmain/dummy/SDL_dummy_main.c)
+    add_library(SDL2main STATIC src/SDLmain/dummy/SDL_dummy_main.c)
 #endif()
-target_include_directories(SDLmain PRIVATE "include/SDL2")
+#add_library(SDL2::SDL2ain ALIAS SDL2main)
+target_include_directories(SDL2main PRIVATE "include/SDL2")
 
 # SDLtest library...
-add_library(SDLtest STATIC
-    src/test/SDL_test_assert.c
-    src/test/SDL_test_common.c
-    src/test/SDL_test_compare.c
-    src/test/SDL_test_crc32.c
-    src/test/SDL_test_font.c
-    src/test/SDL_test_fuzzer.c
-    src/test/SDL_test_harness.c
-    src/test/SDL_test_imageBlit.c
-    src/test/SDL_test_imageBlitBlend.c
-    src/test/SDL_test_imageFace.c
-    src/test/SDL_test_imagePrimitives.c
-    src/test/SDL_test_imagePrimitivesBlend.c
-    src/test/SDL_test_log.c
-    src/test/SDL_test_md5.c
-    src/test/SDL_test_memory.c
-    src/test/SDL_test_random.c 
+add_library(SDL2test STATIC
+  src/test/SDL_test_assert.c
+  src/test/SDL_test_common.c
+  src/test/SDL_test_compare.c
+  src/test/SDL_test_crc32.c
+  src/test/SDL_test_font.c
+  src/test/SDL_test_fuzzer.c
+  src/test/SDL_test_harness.c
+  src/test/SDL_test_imageBlit.c
+  src/test/SDL_test_imageBlitBlend.c
+  src/test/SDL_test_imageFace.c
+  src/test/SDL_test_imagePrimitives.c
+  src/test/SDL_test_imagePrimitivesBlend.c
+  src/test/SDL_test_log.c
+  src/test/SDL_test_md5.c
+  src/test/SDL_test_memory.c
+  src/test/SDL_test_random.c
+)
+add_library(SDL2::SDL2test ALIAS SDL2test)
+target_include_directories(SDL2test PRIVATE "include/SDL2")
+target_include_directories(SDL2test
+  INTERFACE
+    "$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>"
+    "$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include/SDL2>"
+    "$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include>"
+    "$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include/SDL2>"
+    "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
+    "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/SDL2>"
 )
-target_include_directories(SDLtest PRIVATE "include/SDL2")
 
-if(SDL2TESTS)
-    if(NOT (WIN32 OR APPLE OR CYGWIN OR HAIKU OR BEOS))
-      find_library(MATH_LIBRARY m)
-    endif()
+if(SDL2COMPAT_TESTS)
+  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()
+  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/SDL2")
-        if(MINGW)
-          target_link_libraries(${_NAME} mingw32 SDLmain SDLtest SDL)
-        else()
-          target_link_libraries(${_NAME} SDLmain SDLtest 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(checkkeysthreads "test/checkkeysthreads.c")
-    test_program(controllermap "test/controllermap.c")
-    test_program(loopwave "test/loopwave.c;test/testutils.c")
-    test_program(loopwavequeue "test/loopwavequeue.c;test/testutils.c")
-    test_program(testatomic "test/testatomic.c")
-    test_program(testaudiocapture "test/testaudiocapture.c")
-    test_program(testaudiohotplug "test/testaudiohotplug.c;test/testutils.c")
-    test_program(testaudioinfo "test/testaudioinfo.c")
-    test_program(testbounds "test/testbounds.c")
-    test_program(testcustomcursor "test/testcustomcursor.c")
-    test_program(testdisplayinfo "test/testdisplayinfo.c")
-    test_program(testdraw2 "test/testdraw2.c")
-    test_program(testdrawchessboard "test/testdrawchessboard.c")
-    test_program(testdropfile "test/testdropfile.c")
-    test_program(testerror "test/testerror.c")
-    test_program(testevdev "test/testevdev.c")
-    test_program(testfile "test/testfile.c")
-    test_program(testfilesystem "test/testfilesystem.c")
-    test_program(testgamecontroller "test/testgamecontroller.c")
-    test_program(testgeometry "test/testgeometry.c;test/testutils.c")
-    test_program(testgesture "test/testgesture.c")
-    test_program(testhaptic "test/testhaptic.c")
-    test_program(testhittesting "test/testhittesting.c")
-    test_program(testhotplug "test/testhotplug.c")
-    test_program(testiconv "test/testiconv.c;test/testutils.c")
-    test_program(testime "test/testime.c;test/testutils.c")
-    test_program(testintersections "test/testintersections.c")
-    test_program(testjoystick "test/testjoystick.c")
-    test_program(testkeys "test/testkeys.c")
-    test_program(testloadso "test/testloadso.c")
-    test_program(testlocale "test/testlocale.c")
-    test_program(testlock "test/testlock.c")
-    test_program(testmessage "test/testmessage.c")
-    test_program(testmouse "test/testmouse.c")
-    test_program(testmultiaudio "test/testmultiaudio.c;test/testutils.c")
-    test_program(testnative "test/testnative.c;test/testutils.c")
-    test_program(testoverlay2 "test/testoverlay2.c;test/testutils.c;test/testyuv_cvt.c")
-    test_program(testplatform "test/testplatform.c")
-    test_program(testpower "test/testpower.c")
-    test_program(testqsort "test/testqsort.c")
-    test_program(testrelative "test/testrelative.c")
-    test_program(testrendercopyex "test/testrendercopyex.c;test/testutils.c")
-    test_program(testrendertarget "test/testrendertarget.c;test/testutils.c")
-    test_program(testresample "test/testresample.c")
-    test_program(testrumble "test/testrumble.c")
-    test_program(testscale "test/testscale.c;test/testutils.c")
-    test_program(testsem "test/testsem.c")
-    test_program(testsensor "test/testsensor.c")
-    test_program(testshape "test/testshape.c")
-    test_program(testsprite2 "test/testsprite2.c;test/testutils.c")
-    test_program(testspriteminimal "test/testspriteminimal.c;test/testutils.c")
-    test_program(teststreaming "test/teststreaming.c;test/testutils.c")
-    test_program(testsurround "test/testsurround.c")
-    test_program(testthread "test/testthread.c")
-    test_program(testtimer "test/testtimer.c")
-    test_program(testurl "test/testurl.c")
-    test_program(testver "test/testver.c")
-    test_program(testviewport "test/testviewport.c;test/testutils.c")
-    test_program(testvulkan "test/testvulkan.c")
-    test_program(testwm2 "test/testwm2.c")
-    test_program(testyuv "test/testyuv.c;test/testyuv_cvt.c")
-    test_program(torturethread "test/torturethread.c")
-    test_program(testgl2 "test/testgl2.c")
-    test_program(testgles "test/testgles.c")
-    test_program(testgles2 "test/testgles2.c")
-    test_program(testgles2_sdf "test/testgles2_sdf.c;test/testutils.c")
-
-    list(APPEND TESTAUTOMATION_SRCS "test/testautomation.c")
-    list(APPEND TESTAUTOMATION_SRCS "test/testautomation_audio.c")
-    list(APPEND TESTAUTOMATION_SRCS "test/testautomation_guid.c")
-    list(APPEND TESTAUTOMATION_SRCS "test/testautomation_main.c")
-    list(APPEND TESTAUTOMATION_SRCS "test/testautomation_platform.c")
-    list(APPEND TESTAUTOMATION_SRCS "test/testautomation_sdltest.c")
-    list(APPEND TESTAUTOMATION_SRCS "test/testautomation_syswm.c")
-    list(APPEND TESTAUTOMATION_SRCS "test/testautomation_hints.c")
-    list(APPEND TESTAUTOMATION_SRCS "test/testautomation_math.c")
-    list(APPEND TESTAUTOMATION_SRCS "test/testautomation_rect.c")
-    list(APPEND TESTAUTOMATION_SRCS "test/testautomation_stdlib.c")
-    list(APPEND TESTAUTOMATION_SRCS "test/testautomation_timer.c")
-    list(APPEND TESTAUTOMATION_SRCS "test/testautomation_clipboard.c")
-    list(APPEND TESTAUTOMATION_SRCS "test/testautomation_joystick.c")
-    list(APPEND TESTAUTOMATION_SRCS "test/testautomation_mouse.c")
-    list(APPEND TESTAUTOMATION_SRCS "test/testautomation_render.c")
-    list(APPEND TESTAUTOMATION_SRCS "test/testautomation_video.c")
-    list(APPEND TESTAUTOMATION_SRCS "test/testautomation_events.c")
-    list(APPEND TESTAUTOMATION_SRCS "test/testautomation_keyboard.c")
-    list(APPEND TESTAUTOMATION_SRCS "test/testautomation_pixels.c")
-    list(APPEND TESTAUTOMATION_SRCS "test/testautomation_rwops.c")
-    list(APPEND TESTAUTOMATION_SRCS "test/testautomation_surface.c")
-    test_program(testautomation "${TESTAUTOMATION_SRCS}")
-
-    if(OPENGL_FOUND)
-      if(CMAKE_VERSION VERSION_LESS 3.10 OR NOT OPENGL_opengl_LIBRARY)
-        target_link_libraries(testgl2 ${OPENGL_gl_LIBRARY})
-      else()
-        target_link_libraries(testgl2 ${OPENGL_opengl_LIBRARY})
-      endif()
+  macro(test_program _NAME _SRCS)
+    add_executable(${_NAME} ${_SRCS})
+    target_include_directories(${_NAME} PRIVATE "include/SDL2")
+    if(MINGW)
+      target_link_libraries(${_NAME} PRIVATE mingw32 SDL2main SDL2test SDL2)
+    else()
+      target_link_libraries(${_NAME} PRIVATE SDL2main SDL2test SDL2)
+    endif()
+    # Turn off MSVC's aggressive C runtime warnings for the old test programs.
+    if(MSVC)
+      target_compile_definitions(${_NAME} PRIVATE ${HAVE_OPENGL_DEFINE} _CRT_SECURE_NO_WARNINGS _CRT_SECURE_NO_DEPRECATE _CRT_NONSTDC_NO_DEPRECATE)
+    elseif(APPLE)
+      target_compile_definitions(${_NAME} PRIVATE ${HAVE_OPENGL_DEFINE} GL_SILENCE_DEPRECATION=1)
+      target_link_libraries(${_NAME} PRIVATE "-Wl,-framework,Cocoa")
+    else()
+      target_compile_definitions(${_NAME} PRIVATE ${HAVE_OPENGL_DEFINE})
     endif()
+    if(MATH_LIBRARY)
+      target_link_libraries(${_NAME} PRIVATE ${MATH_LIBRARY})
+    endif()
+  endmacro()
+
+  test_program(checkkeys "test/checkkeys.c")
+  test_program(checkkeysthreads "test/checkkeysthreads.c")
+  test_program(controllermap "test/controllermap.c")
+  test_program(loopwave "test/loopwave.c;test/testutils.c")
+  test_program(loopwavequeue "test/loopwavequeue.c;test/testutils.c")
+  test_program(testatomic "test/testatomic.c")
+  test_program(testaudiocapture "test/testaudiocapture.c")
+  test_program(testaudiohotplug "test/testaudiohotplug.c;test/testutils.c")
+  test_program(testaudioinfo "test/testaudioinfo.c")
+  test_program(testbounds "test/testbounds.c")
+  test_program(testcustomcursor "test/testcustomcursor.c")
+  test_program(testdisplayinfo "test/testdisplayinfo.c")
+  test_program(testdraw2 "test/testdraw2.c")
+  test_program(testdrawchessboard "test/testdrawchessboard.c")
+  test_program(testdropfile "test/testdropfile.c")
+  test_program(testerror "test/testerror.c")
+  test_program(testevdev "test/testevdev.c")
+  test_program(testfile "test/testfile.c")
+  test_program(testfilesystem "test/testfilesystem.c")
+  test_program(testgamecontroller "test/testgamecontroller.c")
+  test_program(testgeometry "test/testgeometry.c;test/testutils.c")
+  test_program(testgesture "test/testgesture.c")
+  test_program(testhaptic "test/testhaptic.c")
+  test_program(testhittesting "test/testhittesting.c")
+  test_program(testhotplug "test/testhotplug.c")
+  test_program(testiconv "test/testiconv.c;test/testutils.c")
+  test_program(testime "test/testime.c;test/testutils.c")
+  test_program(testintersections "test/testintersections.c")
+  test_program(testjoystick "test/testjoystick.c")
+  test_program(testkeys "test/testkeys.c")
+  test_program(testloadso "test/testloadso.c")
+  test_program(testlocale "test/testlocale.c")
+  test_program(testlock "test/testlock.c")
+  test_program(testmessage "test/testmessage.c")
+  test_program(testmouse "test/testmouse.c")
+  test_program(testmultiaudio "test/testmultiaudio.c;test/testutils.c")
+  test_program(testnative "test/testnative.c;test/testutils.c")
+  test_program(testoverlay2 "test/testoverlay2.c;test/testutils.c;test/testyuv_cvt.c")
+  test_program(testplatform "test/testplatform.c")
+  test_program(testpower "test/testpower.c")
+  test_program(testqsort "test/testqsort.c")
+  test_program(testrelative "test/testrelative.c")
+  test_program(testrendercopyex "test/testrendercopyex.c;test/testutils.c")
+  test_program(testrendertarget "test/testrendertarget.c;test/testutils.c")
+  test_program(testresample "test/testresample.c")
+  test_program(testrumble "test/testrumble.c")
+  test_program(testscale "test/testscale.c;test/testutils.c")
+  test_program(testsem "test/testsem.c")
+  test_program(testsensor "test/testsensor.c")
+  test_program(testshape "test/testshape.c")
+  test_program(testsprite2 "test/testsprite2.c;test/testutils.c")
+  test_program(testspriteminimal "test/testspriteminimal.c;test/testutils.c")
+  test_program(teststreaming "test/teststreaming.c;test/testutils.c")
+  test_program(testsurround "test/testsurround.c")
+  test_program(testthread "test/testthread.c")
+  test_program(testtimer "test/testtimer.c")
+  test_program(testurl "test/testurl.c")
+  test_program(testver "test/testver.c")
+  test_program(testviewport "test/testviewport.c;test/testutils.c")
+  test_program(testvulkan "test/testvulkan.c")
+  test_program(testwm2 "test/testwm2.c")
+  test_program(testyuv "test/testyuv.c;test/testyuv_cvt.c")
+  test_program(torturethread "test/torturethread.c")
+  test_program(testgl2 "test/testgl2.c")
+  test_program(testgles "test/testgles.c")
+  test_program(testgles2 "test/testgles2.c")
+  test_program(testgles2_sdf "test/testgles2_sdf.c;test/testutils.c")
+
+  list(APPEND TESTAUTOMATION_SRCS "test/testautomation.c")
+  list(APPEND TESTAUTOMATION_SRCS "test/testautomation_audio.c")
+  list(APPEND TESTAUTOMATION_SRCS "test/testautomation_guid.c")
+  list(APPEND TESTAUTOMATION_SRCS "test/testautomation_main.c")
+  list(APPEND TESTAUTOMATION_SRCS "test/testautomation_platform.c")
+  list(APPEND TESTAUTOMATION_SRCS "test/testautomation_sdltest.c")
+  list(APPEND TESTAUTOMATION_SRCS "test/testautomation_syswm.c")
+  list(APPEND TESTAUTOMATION_SRCS "test/testautomation_hints.c")
+  list(APPEND TESTAUTOMATION_SRCS "test/testautomation_math.c")
+  list(APPEND TESTAUTOMATION_SRCS "test/testautomation_rect.c")
+  list(APPEND TESTAUTOMATION_SRCS "test/testautomation_stdlib.c")
+  list(APPEND TESTAUTOMATION_SRCS "test/testautomation_timer.c")
+  list(APPEND TESTAUTOMATION_SRCS "test/testautomation_clipboard.c")
+  list(APPEND TESTAUTOMATION_SRCS "test/testautomation_joystick.c")
+  list(APPEND TESTAUTOMATION_SRCS "test/testautomation_mouse.c")
+  list(APPEND TESTAUTOMATION_SRCS "test/testautomation_render.c")
+  list(APPEND TESTAUTOMATION_SRCS "test/testautomation_video.c")
+  list(APPEND TESTAUTOMATION_SRCS "test/testautomation_events.c")
+  list(APPEND TESTAUTOMATION_SRCS "test/testautomation_keyboard.c")
+  list(APPEND TESTAUTOMATION_SRCS "test/testautomation_pixels.c")
+  list(APPEND TESTAUTOMATION_SRCS "test/testautomation_rwops.c")
+  list(APPEND TESTAUTOMATION_SRCS "test/testautomation_surface.c")
+  test_program(testautomation "${TESTAUTOMATION_SRCS}")
+
+  if(OPENGL_FOUND)
+    if(CMAKE_VERSION VERSION_LESS 3.10 OR NOT OPENGL_opengl_LIBRARY)
+      target_link_libraries(testgl2 PRIVATE ${OPENGL_gl_LIBRARY})
+    else()
+      target_link_libraries(testgl2 PRIVATE ${OPENGL_opengl_LIBRARY})
+    endif()
+  endif()
 
-    foreach(fname
-      "axis.bmp"
-      "button.bmp"
-      "controllermap.bmp"
-      "controllermap_back.bmp"
-      "icon.bmp"
-      "moose.dat"
-      "sample.bmp"
-      "sample.wav"
-      "testgles2_sdf_img_normal.bmp"
-      "testgles2_sdf_img_sdf.bmp"
-      "testyuv.bmp"
-      "unifont-13.0.06.hex"
-      "utf8.txt")
-        file(COPY "${CMAKE_SOURCE_DIR}/test/${fname}" DESTINATION "${CMAKE_BINARY_DIR}")
-    endforeach()
+  foreach(fname
+    "axis.bmp"
+    "button.bmp"
+    "controllermap.bmp"
+    "controllermap_back.bmp"
+    "icon.bmp"
+    "moose.dat"
+    "sample.bmp"
+    "sample.wav"
+    "testgles2_sdf_img_normal.bmp"
+    "testgles2_sdf_img_sdf.bmp"
+    "testyuv.bmp"
+    "unifont-13.0.06.hex"
+    "utf8.txt")
+      file(COPY "${CMAKE_SOURCE_DIR}/test/${fname}" DESTINATION "${CMAKE_BINARY_DIR}")
+  endforeach()
 endif()
 
-install(TARGETS SDL SDLmain SDLtest
-  LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
-  ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
-  RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
-)
+set(installed_targets SDL2)
+
+if(SDL2COMPAT_STATICDEVEL AND SDL2COMPAT_DEVEL)
+  add_library(SDL2-static STATIC ${SDL2COMPAT_SRCS})
+  add_library(SDL2::SDL2-static ALIAS SDL2-static)
+  target_include_directories(SDL2-static
+    PRIVATE
+      ${SDL3_INCLUDE_DIRS}
+    INTERFACE
+      "$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>"
+      "$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include/SDL2>"
+      "$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include>"
+      "$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include/SDL2>"
+      "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
+      "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/SDL2>"
+  )
+  target_compile_definitions(SDL2-static PRIVATE _REENTRANT)
+  target_link_libraries(SDL2-static PRIVATE ${CMAKE_DL_LIBS})
+  set_target_properties(SDL2-static PROPERTIES
+    VERSION "${PROJECT_VERSION}"
+    OUTPUT_NAME "SDL2"
+  )
+  if(CMAKE_STATIC_LIBRARY_PREFIX STREQUAL "" AND CMAKE_STATIC_LIBRARY_SUFFIX STREQUAL ".lib")
+    set_target_properties(SDL2-static PROPERTIES
+      OUTPUT_NAME "SDL2-static"
+    )
+  endif()
 
-if(SDL2DEVEL)
-  install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
+  list(APPEND installed_targets SDL2-static)
+endif()
+
+if(SDL2COMPAT_DEVEL)
+  if(WIN32 AND NOT MINGW)
+    set(SDL23COMPAT_INSTALL_CMAKEDIR_DEFAULT "cmake")
+    set(LICENSES_PREFIX "licenses/SDL2")
+  else()
+    set(SDL23COMPAT_INSTALL_CMAKEDIR_DEFAULT "${CMAKE_INSTALL_LIBDIR}/cmake/SDL2")
+    set(LICENSES_PREFIX "${CMAKE_INSTALL_DATAROOTDIR}/licenses/SDL2")
+  endif()
+  set(SDL23COMPAT_INSTALL_CMAKEDIR "${SDL23COMPAT_INSTALL_CMAKEDIR_DEFAULT}" CACHE STRING "Location where to install SDL2Config.cmake")
+
+  list(APPEND installed_targets SDL2main SDL2test)
+  foreach(target ${installed_targets})
+    install(TARGETS ${target} EXPORT ${target}Targets
+      ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
+      LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
+      RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
+    )
+    install(EXPORT ${target}Targets
+      FILE ${target}Targets.cmake
+      NAMESPACE SDL2::
+      DESTINATION "${SDL23COMPAT_INSTALL_CMAKEDIR}"
+    )
+  endforeach()
+  configure_package_config_file(SDL2Config.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/SDL2Config.cmake"
+    PATH_VARS CMAKE_INSTALL_PREFIX CMAKE_INSTALL_FULL_BINDIR CMAKE_INSTALL_FULL_INCLUDEDIR CMAKE_INSTALL_FULL_LIBDIR
+    INSTALL_DESTINATION "${SDL23COMPAT_INSTALL_CMAKEDIR}"
+  )
+  write_basic_package_version_file("${CMAKE_CURRENT_BINARY_DIR}/SDL2ConfigVersion.cmake"
+    VERSION ${sdl2_compat_VERSION}
+    COMPATIBILITY AnyNewerVersion
+  )
+  install(
+    FILES
+      ${CMAKE_CURRENT_BINARY_DIR}/SDL2Config.cmake
+      ${CMAKE_CURRENT_BINARY_DIR}/SDL2ConfigVersion.cmake
+    DESTINATION "${SDL23COMPAT_INSTALL_CMAKEDIR}"
+  )
+
+  file(GLOB SDL2_INCLUDE_FILES ${PROJECT_SOURCE_DIR}/include/SDL2/*.h)
+  set(SDL2_COPIED_INCLUDE_FILES)
+  foreach(_hdr IN LISTS SDL2_INCLUDE_FILES)
+    if(_hdr MATCHES ".*(SDL_config).*")
+      # FIXME: how to handle SDL_config.h? Generate a new one from SDL_co

(Patch may be truncated, please check the link at the top of this post.)