浏览代码

cmake: bump minimum required CMake version to 3.16

main features:

- No more sdl-build-options/sdl-shared-build-options/sdl-global-options
- Dependency information is stored on SDL3-collector for sdl3.pc
- Use helper functions to modify the SDL targets;
    - sdl_sources to add sources
    - sdl_glob_sources to add glob soruces
    - sdl_link_dependency to add a link dependency that might also
      appear in sdl3.pc/SDL3Config.cmake
    - sdl_compile_definitions to add macro's
    - sdl_compile_options for compile options
    - sdl_include_directories for include directories
  They avoid repeated checks for existence of the SDL targets
- A nice feature of the previous is the ability to generate
  a sdl3.pc or SDL3Config.cmake that describes its dependencies
  accurately.

various:

- remove duplicate libc symbol list
- add CheckVulkan
- remove unused HAVE_MPROTECT
- add checks for getpagesize
Anonymous Maarten 2 年之前
父节点
当前提交
3ab4665956

文件差异内容过多而无法显示
+ 321 - 430
CMakeLists.txt


+ 75 - 0
cmake/FindRPi_BcmHost.cmake

@@ -0,0 +1,75 @@
+include(FeatureSummary)
+set_package_properties(RPi_BcmHost PROPERTIES
+    URL "https://github.com/raspberrypi/firmware"
+    DESCRIPTION "Broadcom VideoCore host API library"
+)
+
+set(RPi_BcmHost_PKG_CONFIG_SPEC bcm_host)
+
+find_package(PkgConfig QUIET)
+pkg_check_modules(PC_RPi_BcmHost QUIET ${RPi_BcmHost_PKG_CONFIG_SPEC})
+
+find_library(RPi_BcmHost_bcm_host_LIBRARY
+    NAMES bcm_host
+    HINTS
+        ${PC_RPi_BcmHost_LIBRARY_DIRS}
+        /opt/vc/lib
+)
+
+find_path(RPi_BcmHost_bcm_host_h_PATH
+    NAMES bcm_host.h
+    HINTS
+        ${PC_RPi_BcmHost_INCLUDE_DIRS}
+        /opt/vc/include
+)
+
+if(PC_RPi_BcmHost_FOUND)
+    include("${CMAKE_CURRENT_LIST_DIR}/PkgConfigHelper.cmake")
+    get_flags_from_pkg_config("${RPi_BcmHost_bcm_host_LIBRARY}" "PC_RPi_BcmHost" "_RPi_BcmHost")
+else()
+    set(_RPi_BcmHost_include_dirs
+        /opt/vc/include
+        /opt/vc/include/interface/vcos/pthreads
+        /opt/vc/include/interface/vmcs_host/linux
+    )
+    set(_RPi_BcmHost_compile_options
+        -DUSE_VCHIQ_ARM
+    )
+    set(_RPi_BcmHost_link_libraries
+        -lvcos -lvchiq_arm
+    )
+    set(_RPi_BcmHost_link_options
+        -pthread
+    )
+    set(_RPi_BcmHost_link_directories
+        /opt/vc/lib
+    )
+endif()
+
+set(RPi_BcmHost_INCLUDE_DIRS "${_RPi_BcmHost_include_dirs}" CACHE STRING "Extra include dirs of bcm_host")
+
+set(RPi_BcmHost_COMPILE_OPTIONS "${_RPi_BcmHost_compile_options}" CACHE STRING "Extra compile options of bcm_host")
+
+set(RPi_BcmHost_LINK_LIBRARIES "${_RPi_BcmHost_link_libraries}" CACHE STRING "Extra link libraries of bcm_host")
+
+set(RPi_BcmHost_LINK_OPTIONS "${_RPi_BcmHost_link_options}" CACHE STRING "Extra link flags of bcm_host")
+
+set(RPi_BcmHost_LINK_DIRECTORIES "${_RPi_BcmHost_link_directories}" CACHE PATH "Extra link directories of bcm_host")
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(RPi_BcmHost
+    REQUIRED_VARS RPi_BcmHost_bcm_host_LIBRARY RPi_BcmHost_bcm_host_h_PATH
+)
+
+if(RPi_BcmHost_FOUND)
+    if(NOT TARGET RPi_BcmHost::RPi_BcmHost)
+        add_library(RPi_BcmHost::RPi_BcmHost INTERFACE IMPORTED)
+        set_target_properties(RPi_BcmHost::RPi_BcmHost PROPERTIES
+            INTERFACE_INCLUDE_DIRECTORIES "${RPi_BcmHost_INCLUDE_DIRS}"
+            INTERFACE_COMPILE_OPTIONS "${RPi_BcmHost_COMPILE_OPTIONS}"
+            INTERFACE_LINK_LIBRARIES "${RPi_BcmHost_LINK_LIBRARIES}"
+            INTERFACE_LINK_OPTIONS "${RPi_BcmHost_LINK_OPTIONS}"
+            INTERFACE_LINK_DIRECTORIES "${RPi_BcmHost_LINK_DIRECTORIES}"
+          )
+    endif()
+endif()

+ 59 - 0
cmake/FindRPi_BrcmEGL.cmake

@@ -0,0 +1,59 @@
+include(FeatureSummary)
+set_package_properties(RPi_BrcmEGL PROPERTIES
+    URL "https://github.com/raspberrypi/firmware"
+    DESCRIPTION "Fake brcmEGL package for RPi"
+)
+
+set(RPi_BrcmEGL_PKG_CONFIG_SPEC brcmegl)
+
+find_package(PkgConfig QUIET)
+pkg_check_modules(PC_RPi_BrcmEGL QUIET ${RPi_BrcmEGL_PKG_CONFIG_SPEC})
+
+find_package(RPi_BcmHost)
+
+find_library(RPi_BrcmEGL_brcmEGL_LIBRARY
+    NAMES brcmEGL
+    HINTS
+        ${PC_RPi_BrcmEGL_LIBRARY_DIRS}
+        /opt/vc/lib
+)
+
+find_path(RPi_BrcmEGL_EGL_eglplatform_h_PATH
+    NAMES EGL/eglplatform.h
+    HINTS
+        ${PC_RPi_BrcmEGL_INCLUDE_DIRS}
+        /opt/vc/include
+)
+
+if(PC_RPi_BrcmEGL_FOUND)
+    include("${CMAKE_CURRENT_LIST_DIR}/PkgConfigHelper.cmake")
+    get_flags_from_pkg_config("${RPi_BrcmEGL_brcmEGL_LIBRARY}" "PC_RPi_BrcmEGL" "_RPi_BrcmEGL")
+endif()
+
+set(RPi_BrcmEGL_INCLUDE_DIRS "${_RPi_BrcmEGL_include_dirs}" CACHE STRING "Extra include dirs of brcmEGL")
+
+set(RPi_BrcmEGL_COMPILE_OPTIONS "${_RPi_BrcmEGL_compile_options}" CACHE STRING "Extra compile options of brcmEGL")
+
+set(RPi_BrcmEGL_LINK_LIBRARIES "${_RPi_BrcmEGL_link_libraries}" CACHE STRING "Extra link libraries of brcmEGL")
+
+set(RPi_BrcmEGL_LINK_OPTIONS "${_RPi_BrcmEGL_link_options}" CACHE STRING "Extra link flags of brcmEGL")
+
+set(RPi_BrcmEGL_LINK_DIRECTORIES "${_RPi_BrcmEGL_link_directories}" CACHE PATH "Extra link directories of brcmEGL")
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(RPi_BrcmEGL
+    REQUIRED_VARS RPi_BrcmEGL_brcmEGL_LIBRARY RPi_BrcmEGL_EGL_eglext_brcm_h_PATH RPi_BcmHost_FOUND
+)
+
+if(RPi_BrcmEGL_FOUND)
+    if(NOT TARGET RPi_BcmHost::RPi_BcmHost)
+        add_library(RPi_BcmHost::RPi_BcmHost INTERFACE IMPORTED)
+        set_target_properties(RPi_BcmHost::RPi_BcmHost PROPERTIES
+            INTERFACE_INCLUDE_DIRECTORIES "${RPi_BrcmEGL_INCLUDE_DIRS}"
+            INTERFACE_COMPILE_OPTIONS "${RPi_BrcmEGL_COMPILE_OPTIONS}"
+            INTERFACE_LINK_LIBRARIES "${RPi_BrcmEGL_LINK_LIBRARIES};RPi_BcmHost::RPi_BcmHost"
+            INTERFACE_LINK_OPTIONS "${RPi_BrcmEGL_LINK_OPTIONS}"
+            INTERFACE_LINK_DIRECTORIES "${RPi_BrcmEGL_LINK_DIRECTORIES}"
+        )
+    endif()
+endif()

+ 39 - 0
cmake/PkgConfigHelper.cmake

@@ -0,0 +1,39 @@
+# Helper for Find modules
+
+function(get_flags_from_pkg_config _library _pc_prefix _out_prefix)
+  if("${_library}" MATCHES "${CMAKE_STATIC_LIBRARY_SUFFIX}$")
+    set(_include_dirs ${_pc_prefix}_STATIC_INCLUDE_DIRS)
+    set(_cflags ${_pc_prefix}_STATIC_CFLAGS_OTHER)
+    set(_link_libraries ${_pc_prefix}_STATIC_LIBRARIES)
+    set(_link_options ${_pc_prefix}_STATIC_LDFLAGS_OTHER)
+    set(_library_dirs ${_pc_prefix}_STATIC_LIBRARY_DIRS)
+  else()
+    set(_include_dirs ${_pc_prefix}_INCLUDE_DIRS)
+    set(_cflags ${_pc_prefix}_CFLAGS_OTHER)
+    set(_link_libraries ${_pc_prefix}_LIBRARIES)
+    set(_link_options ${_pc_prefix}_LDFLAGS_OTHER)
+    set(_library_dirs ${_pc_prefix}_LIBRARY_DIRS)
+  endif()
+
+  # The *_LIBRARIES lists always start with the library itself
+  list(POP_FRONT "${_link_libraries}")
+
+  # Work around CMake's flag deduplication when pc files use `-framework A` instead of `-Wl,-framework,A`
+  string(REPLACE "-framework;" "-Wl,-framework," "_filtered_link_options" "${${_link_options}}")
+
+  set(${_out_prefix}_include_dirs
+      "${${_include_dirs}}"
+      PARENT_SCOPE)
+  set(${_out_prefix}_compile_options
+      "${${_cflags}}"
+      PARENT_SCOPE)
+  set(${_out_prefix}_link_libraries
+      "${${_link_libraries}}"
+      PARENT_SCOPE)
+  set(${_out_prefix}_link_options
+      "${_filtered_link_options}"
+      PARENT_SCOPE)
+  set(${_out_prefix}_link_directories
+      "${${_library_dirs}}"
+      PARENT_SCOPE)
+endfunction()

+ 18 - 16
cmake/SDL3Config.cmake.in

@@ -23,19 +23,28 @@ if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/SDL3sharedTargets.cmake")
   set(SDL3_SDL3-shared_FOUND TRUE)
 endif()
 
+macro(find_sdl3_static_dependencies)
+@SDL_FIND_PKG_CONFIG_COMMANDS@
+endmacro()
+
 # Find SDL3::SDL3-static
 if(_sdl3_framework)
+  set(SDL3_SDL3-static_FOUND TRUE)
+  find_sdl3_static_dependencies()
   find_package(SDL3-static CONFIG)
-  if(SDL3-static_FOUND)
+  if(SDL3_SDL3-static_FOUND AND SDL3-static_FOUND)
     set(SDL3_SDL3-static_FOUND TRUE)
   endif()
 else()
   if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/SDL3staticTargets.cmake")
-    if(ANDROID OR HAIKU)
-      enable_language(CXX)
-    endif()
-    include("${CMAKE_CURRENT_LIST_DIR}/SDL3staticTargets.cmake")
     set(SDL3_SDL3-static_FOUND TRUE)
+    find_sdl3_static_dependencies()
+    if(SDL3_SDL3-static_FOUND)
+      if(ANDROID OR HAIKU)
+        enable_language(CXX)
+      endif()
+      include("${CMAKE_CURRENT_LIST_DIR}/SDL3staticTargets.cmake")
+    endif()
   endif()
 endif()
 
@@ -52,21 +61,14 @@ if(_sdl3_framework)
   endif()
 else()
   if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/SDL3testTargets.cmake")
-    include("${CMAKE_CURRENT_LIST_DIR}/SDL3testTargets.cmake")
     set(SDL3_SDL3_test_FOUND TRUE)
+@SDL_TEST_FIND_PKG_CONFIG_COMMANDS@
+    if(SDL3_SDL3_test_FOUND)
+      include("${CMAKE_CURRENT_LIST_DIR}/SDL3testTargets.cmake")
+    endif()
   endif()
 endif()
 
-include("${CMAKE_CURRENT_LIST_DIR}/sdlfind.cmake")
-
-set(SDL_ALSA @SDL_ALSA@)
-set(SDL_ALSA_SHARED @SDL_ALSA_SHARED@)
-if(SDL_ALSA AND NOT SDL_ALSA_SHARED AND TARGET SDL3::SDL3-static)
-  sdlFindALSA()
-endif()
-unset(SDL_ALSA)
-unset(SDL_ALSA_SHARED)
-
 check_required_components(SDL3)
 
 function(_sdl_create_target_alias_compat NEW_TARGET TARGET)

+ 62 - 54
cmake/macros.cmake

@@ -1,9 +1,5 @@
 macro(add_to_alloptions _NEWNAME)
   list(APPEND ALLOPTIONS ${_NEWNAME})
-  string(LENGTH ${_NEWNAME} _SLEN)
-  if(${LONGESTOPTIONNAME} LESS ${_SLEN})
-    set(LONGESTOPTIONNAME ${_SLEN})
-  endif()
 endmacro()
 
 macro(set_option _NAME _DESC)
@@ -27,15 +23,6 @@ macro(option_string _NAME _DESC _VALUE)
   set(HAVE_${_NAME} ${_VALUE})
 ENDMACRO()
 
-# Message Output
-macro(message_warn _TEXT)
-  message(WARNING "${_TEXT}")
-endmacro()
-
-macro(message_error _TEXT)
-  message(FATAL_ERROR "*** ERROR: ${_TEXT}")
-endmacro()
-
 macro(message_bool_option _NAME _VALUE)
   set(_PAD "\t")
   if(${ARGC} EQUAL 3)
@@ -68,27 +55,6 @@ macro(message_tested_option _NAME)
   message(STATUS "  ${_NAME}${_PAD}(Wanted: ${_REQVALUE}): ${HAVE_${_STRIPPEDNAME}}")
 endmacro()
 
-function(listtostr LIST OUTPUT)
-  if(${ARGC} EQUAL 3)
-    # prefix for each element
-    set(LPREFIX ${ARGV2})
-  else()
-    set(LPREFIX "")
-  endif()
-  # Do not use string(REPLACE ";" " ") here to avoid messing up list entries
-  set(res)
-  foreach(ITEM ${${LIST}})
-    if(ITEM MATCHES "^SHELL:")
-      string(SUBSTRING "${ITEM}" 6 -1 ITEM)
-    endif()
-    if(ITEM)
-      set(res "${res} ${LPREFIX}${ITEM}")
-    endif()
-  endforeach()
-  string(STRIP "${res}" res)
-  set(${OUTPUT} "${res}" PARENT_SCOPE)
-endfunction()
-
 function(find_stringlength_longest_item inList outLength)
   set(maxLength 0)
   foreach(item IN LISTS ${inList})
@@ -111,22 +77,9 @@ function(message_dictlist inList)
   endforeach()
 endfunction()
 
-if(CMAKE_VERSION VERSION_LESS 3.16.0 OR SDL3_SUBPROJECT)
-  # - CMake versions <3.16 do not support the OBJC language
-  # - When SDL is built as a subproject and when the main project does not enable OBJC,
-  #   CMake fails due to missing internal CMake variables (CMAKE_OBJC_COMPILE_OBJECT)
-  #   (reproduced with CMake 3.24.2)
-  macro(CHECK_OBJC_SOURCE_COMPILES SOURCE VAR)
-    set(PREV_REQUIRED_DEFS "${CMAKE_REQUIRED_DEFINITIONS}")
-    set(CMAKE_REQUIRED_DEFINITIONS "-x objective-c ${PREV_REQUIRED_DEFS}")
-    CHECK_C_SOURCE_COMPILES("${SOURCE}" ${VAR})
-    set(CMAKE_REQUIRED_DEFINITIONS "${PREV_REQUIRED_DEFS}")
-  endmacro()
-else()
+if(APPLE)
   include(CheckOBJCSourceCompiles)
-  if (APPLE)
-      enable_language(OBJC)
-  endif()
+  enable_language(OBJC)
 endif()
 
 if(CMAKE_VERSION VERSION_LESS 3.18)
@@ -156,8 +109,63 @@ if(APPLE)
   endif()
 endif()
 
-if(CMAKE_VERSION VERSION_LESS 3.13.0)
-  macro(target_link_directories _TARGET _SCOPE)
-    link_directories(${ARGN})
-  endmacro()
-endif()
+function(SDL_PrintSummary)
+  ##### Info output #####
+  message(STATUS "")
+  message(STATUS "SDL3 was configured with the following options:")
+  message(STATUS "")
+  message(STATUS "Platform: ${CMAKE_SYSTEM}")
+  message(STATUS "64-bit:   ${ARCH_64}")
+  message(STATUS "Compiler: ${CMAKE_C_COMPILER}")
+  message(STATUS "Revision: ${SDL_REVISION}")
+  message(STATUS "Vendor:   ${SDL_VENDOR_INFO}")
+  message(STATUS "")
+  message(STATUS "Subsystems:")
+
+  find_stringlength_longest_item(SDL_SUBSYSTEMS maxLength)
+  foreach(_SUB IN LISTS SDL_SUBSYSTEMS)
+    string(LENGTH ${_SUB} _SUBLEN)
+    math(EXPR _PADLEN "(${maxLength} + 1) - ${_SUBLEN}")
+    string(RANDOM LENGTH ${_PADLEN} ALPHABET " " _PADDING)
+    string(TOUPPER ${_SUB} _OPT)
+    message_bool_option(${_SUB} SDL_${_OPT} ${_PADDING})
+  endforeach()
+  message(STATUS "")
+  message(STATUS "Options:")
+  list(SORT ALLOPTIONS)
+  message_dictlist(ALLOPTIONS)
+  message(STATUS "")
+  message(STATUS " Build Shared Library: ${SDL_SHARED}")
+  message(STATUS " Build Static Library: ${SDL_STATIC}")
+  if(SDL_STATIC)
+    message(STATUS " Build Static Library with Position Independent Code: ${SDL_STATIC_PIC}")
+  endif()
+  if(APPLE)
+    message(STATUS " Build libraries as Apple Framework: ${SDL_FRAMEWORK}")
+  endif()
+  message(STATUS "")
+  if(UNIX)
+    message(STATUS "If something was not detected, although the libraries")
+    message(STATUS "were installed, then make sure you have set the")
+    message(STATUS "CMAKE_C_FLAGS and CMAKE_PREFIX_PATH CMake variables correctly.")
+    message(STATUS "")
+  endif()
+
+  if(WARN_ABOUT_ARM_SIMD_ASM_MIT)
+    message(STATUS "SDL is being built with ARM SIMD optimizations, which")
+    message(STATUS "uses code licensed under the MIT license. If this is a")
+    message(STATUS "problem, please disable that code by rerunning CMake with:")
+    message(STATUS "")
+    message(STATUS "    -DSDL_ARMSIMD=OFF")
+    message(STATUS "")
+  endif()
+
+  if(WARN_ABOUT_ARM_NEON_ASM_MIT)
+    message(STATUS "SDL is being built with ARM NEON optimizations, which")
+    message(STATUS "uses code licensed under the MIT license. If this is a")
+    message(STATUS "problem, please disable that code by rerunning CMake with:")
+    message(STATUS "")
+    message(STATUS "    -DSDL_ARMNEON=OFF")
+    message(STATUS "")
+  endif()
+endfunction()

+ 2 - 3
cmake/sdl3.pc.in

@@ -1,5 +1,3 @@
-# sdl pkg-config source file
-
 prefix=@SDL_PKGCONFIG_PREFIX@
 exec_prefix=${prefix}
 libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@
@@ -7,8 +5,9 @@ includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
 
 Name: sdl3
 Description: Simple DirectMedia Layer is a cross-platform multimedia library designed to provide low level access to audio, keyboard, mouse, joystick, 3D hardware via OpenGL, and 2D video framebuffer.
+URL: https://www.libsdl.org/
 Version: @PROJECT_VERSION@
 Requires.private: @SDL_PC_PRIVATE_REQUIRES@
 Conflicts:
-Libs: -L${libdir} @SDL_RLD_FLAGS@ @SDL_PC_LIBS@ @PKGCONFIG_LIBS_PRIV@ @SDL_PC_STATIC_LIBS@
+Libs: -L${libdir} @SDL_RLD_FLAGS@ @SDL_PC_LIBS@ @SDL_PC_SECTION_LIBS_PRIVATE@ @SDL_PC_STATIC_LIBS@
 Cflags: -I${includedir} -I${includedir}/SDL3 @SDL_PC_CFLAGS@

+ 318 - 272
cmake/sdlchecks.cmake

@@ -1,11 +1,12 @@
 macro(FindLibraryAndSONAME _LIB)
-  cmake_parse_arguments(FLAS "" "" "LIBDIRS" ${ARGN})
+  cmake_parse_arguments(_FLAS "" "" "LIBDIRS" ${ARGN})
 
   string(TOUPPER ${_LIB} _UPPERLNAME)
   string(REGEX REPLACE "\\-" "_" _LNAME "${_UPPERLNAME}")
 
-  find_library(${_LNAME}_LIB ${_LIB} PATHS ${FLAS_LIBDIRS})
+  find_library(${_LNAME}_LIB ${_LIB} PATHS ${_FLAS_LIBDIRS})
 
+  # FIXME: fail FindLibraryAndSONAME when library is not shared.
   if(${_LNAME}_LIB MATCHES ".*\\${CMAKE_SHARED_LIBRARY_SUFFIX}.*" AND NOT ${_LNAME}_LIB MATCHES ".*\\${CMAKE_STATIC_LIBRARY_SUFFIX}.*")
     set(${_LNAME}_SHARED TRUE)
   else()
@@ -16,6 +17,7 @@ macro(FindLibraryAndSONAME _LIB)
     # reduce the library name for shared linking
 
     get_filename_component(_LIB_REALPATH ${${_LNAME}_LIB} REALPATH)  # resolves symlinks
+    get_filename_component(_LIB_LIBDIR ${_LIB_REALPATH} DIRECTORY)
     get_filename_component(_LIB_JUSTNAME ${_LIB_REALPATH} NAME)
 
     if(APPLE)
@@ -24,20 +26,20 @@ macro(FindLibraryAndSONAME _LIB)
       string(REGEX REPLACE "(\\.[0-9]*)\\.[0-9\\.]*$" "\\1" _LIB_REGEXD "${_LIB_JUSTNAME}")
     endif()
 
-    get_filename_component(${_LNAME}_LIBDIR   ${${_LNAME}_LIB} DIRECTORY)
-
-    SET(_DEBUG_FindSONAME FALSE)
-    if(_DEBUG_FindSONAME)
-      message_warn("DYNLIB OUTPUTVAR: ${_LIB} ... ${_LNAME}_LIB")
-      message_warn("DYNLIB ORIGINAL LIB: ${_LIB} ... ${${_LNAME}_LIB}")
-      message_warn("DYNLIB REALPATH LIB: ${_LIB} ... ${_LIB_REALPATH}")
-      message_warn("DYNLIB JUSTNAME LIB: ${_LIB} ... ${_LIB_JUSTNAME}")
-      message_warn("DYNLIB REGEX'd LIB: ${_LIB} ... ${_LIB_REGEXD}")
+    if(NOT EXISTS "${_LIB_LIBDIR}/${_LIB_REGEXD}")
+      set(_LIB_REGEXD "${_LIB_JUSTNAME}")
     endif()
+    set(${_LNAME}_LIBDIR "${_LIB_LIBDIR}")
 
     message(STATUS "dynamic lib${_LIB} -> ${_LIB_REGEXD}")
     set(${_LNAME}_LIB_SONAME ${_LIB_REGEXD})
   endif()
+
+  message(DEBUG "DYNLIB OUTPUTVAR: ${_LIB} ... ${_LNAME}_LIB")
+  message(DEBUG "DYNLIB ORIGINAL LIB: ${_LIB} ... ${${_LNAME}_LIB}")
+  message(DEBUG "DYNLIB REALPATH LIB: ${_LIB} ... ${_LIB_REALPATH}")
+  message(DEBUG "DYNLIB JUSTNAME LIB: ${_LIB} ... ${_LIB_JUSTNAME}")
+  message(DEBUG "DYNLIB SONAME LIB: ${_LIB} ... ${_LIB_REGEXD}")
 endmacro()
 
 macro(CheckDLOPEN)
@@ -48,7 +50,7 @@ macro(CheckDLOPEN)
     check_symbol_exists(dlopen "dlfcn.h" HAVE_DLOPEN_IN_LIBDL)
     cmake_pop_check_state()
     if(HAVE_DLOPEN_IN_LIBDL)
-      list(APPEND SDL_EXTRA_LIBS dl)
+      sdl_link_dependency(dl LIBS dl)
     endif()
   endif()
   if(HAVE_DLOPEN_IN_LIBC OR HAVE_DLOPEN_IN_LIBDL)
@@ -73,11 +75,10 @@ macro(CheckOSS)
 
     if(HAVE_OSS_SYS_SOUNDCARD_H)
       set(HAVE_OSS TRUE)
-      file(GLOB OSS_SOURCES ${SDL3_SOURCE_DIR}/src/audio/dsp/*.c)
+      sdl_glob_sources(${SDL3_SOURCE_DIR}/src/audio/dsp/*.c)
       set(SDL_AUDIO_DRIVER_OSS 1)
-      list(APPEND SOURCE_FILES ${OSS_SOURCES})
       if(NETBSD)
-        list(APPEND SDL_EXTRA_LIBS ossaudio)
+        sdl_link_dependency(oss LIBS ossaudio)
       endif()
       set(HAVE_SDL_AUDIO TRUE)
     endif()
@@ -91,10 +92,10 @@ endmacro()
 # - HAVE_SDL_LOADSO opt
 macro(CheckALSA)
   if(SDL_ALSA)
-    sdlFindALSA()
+    set(ALSA_PKG_CONFIG_SPEC "alsa")
+    find_package(ALSA MODULE)
     if(ALSA_FOUND)
-      file(GLOB ALSA_SOURCES "${SDL3_SOURCE_DIR}/src/audio/alsa/*.c")
-      list(APPEND SOURCE_FILES ${ALSA_SOURCES})
+      sdl_glob_sources("${SDL3_SOURCE_DIR}/src/audio/alsa/*.c")
       set(SDL_AUDIO_DRIVER_ALSA 1)
       set(HAVE_ALSA TRUE)
       set(HAVE_ALSA_SHARED FALSE)
@@ -102,7 +103,7 @@ macro(CheckALSA)
         if(HAVE_SDL_LOADSO)
           FindLibraryAndSONAME("asound")
           if(ASOUND_LIB AND ASOUND_SHARED)
-            target_include_directories(sdl-build-options INTERFACE $<TARGET_PROPERTY:ALSA::ALSA,INTERFACE_INCLUDE_DIRECTORIES>)
+            sdl_link_dependency(alsa INCLUDES $<TARGET_PROPERTY:ALSA::ALSA,INTERFACE_INCLUDE_DIRECTORIES>)
             set(SDL_AUDIO_DRIVER_ALSA_DYNAMIC "\"${ASOUND_LIB_SONAME}\"")
             set(HAVE_ALSA_SHARED TRUE)
           else()
@@ -113,8 +114,9 @@ macro(CheckALSA)
         endif()
       endif()
       if(NOT HAVE_ALSA_SHARED)
-        list(APPEND SDL_CMAKE_DEPENDS ALSA::ALSA)
+        #FIXME: remove this line and property generate sdl3.pc
         list(APPEND SDL_PC_PRIVATE_REQUIRES alsa)
+        sdl_link_dependency(alsa LIBS ALSA::ALSA CMAKE_MODULE ALSA PKG_CONFIG_SPECS "${ALSA_PKG_CONFIG_SPEC}")
       endif()
       set(HAVE_SDL_AUDIO TRUE)
     endif()
@@ -130,26 +132,26 @@ endmacro()
 # - SDL_PIPEWIRE_SHARED opt
 # - HAVE_SDL_LOADSO opt
 macro(CheckPipewire)
-    if(SDL_PIPEWIRE)
-        pkg_check_modules(PKG_PIPEWIRE libpipewire-0.3>=0.3.20)
-        if(PKG_PIPEWIRE_FOUND)
-            set(HAVE_PIPEWIRE TRUE)
-            file(GLOB PIPEWIRE_SOURCES ${SDL3_SOURCE_DIR}/src/audio/pipewire/*.c)
-            list(APPEND SOURCE_FILES ${PIPEWIRE_SOURCES})
-            set(SDL_AUDIO_DRIVER_PIPEWIRE 1)
-            target_include_directories(sdl-build-options SYSTEM INTERFACE ${PKG_PIPEWIRE_INCLUDE_DIRS})
-            if(SDL_PIPEWIRE_SHARED AND NOT HAVE_SDL_LOADSO)
-                message_warn("You must have SDL_LoadObject() support for dynamic Pipewire loading")
-            endif()
-            FindLibraryAndSONAME("pipewire-0.3" LIBDIRS ${PKG_PIPEWIRE_LIBRARY_DIRS})
-            if(SDL_PIPEWIRE_SHARED AND PIPEWIRE_0.3_LIB AND HAVE_SDL_LOADSO)
-                set(SDL_AUDIO_DRIVER_PIPEWIRE_DYNAMIC "\"${PIPEWIRE_0.3_LIB_SONAME}\"")
-                set(HAVE_PIPEWIRE_SHARED TRUE)
-            else()
-                list(APPEND SDL_EXTRA_LDFLAGS ${PKG_PIPEWIRE_LDFLAGS})
-            endif()
-            set(HAVE_SDL_AUDIO TRUE)
-        endif()
+  if(SDL_PIPEWIRE)
+    set(PipeWire_PKG_CONFIG_SPEC libpipewire-0.3>=0.3.20)
+    pkg_check_modules(PC_PIPEWIRE IMPORTED_TARGET ${PipeWire_PKG_CONFIG_SPEC})
+    if(PC_PIPEWIRE_FOUND)
+      set(HAVE_PIPEWIRE TRUE)
+      sdl_glob_sources("${SDL3_SOURCE_DIR}/src/audio/pipewire/*.c")
+      set(SDL_AUDIO_DRIVER_PIPEWIRE 1)
+      if(SDL_PIPEWIRE_SHARED AND NOT HAVE_SDL_LOADSO)
+        message(WARNING "You must have SDL_LoadObject() support for dynamic PipeWire loading")
+      endif()
+      FindLibraryAndSONAME("pipewire-0.3" LIBDIRS ${PC_PIPEWIRE_LIBRARY_DIRS})
+      if(SDL_PIPEWIRE_SHARED AND PIPEWIRE_0.3_LIB AND HAVE_SDL_LOADSO)
+        set(SDL_AUDIO_DRIVER_PIPEWIRE_DYNAMIC "\"${PIPEWIRE_0.3_LIB_SONAME}\"")
+        set(HAVE_PIPEWIRE_SHARED TRUE)
+        sdl_link_dependency(pipewire INCLUDES $<TARGET_PROPERTY:PkgConfig::PC_PIPEWIRE,INTERFACE_INCLUDE_DIRECTORIES>)
+      else()
+        sdl_link_dependency(pipewire LIBS PkgConfig::PC_PIPEWIRE PKG_CONFIG_PREFIX PC_PIPEWIRE PKG_CONFIG_SPECS ${PipeWire_PKG_CONFIG_SPEC})
+      endif()
+      set(HAVE_SDL_AUDIO TRUE)
+      endif()
     endif()
 endmacro()
 
@@ -160,22 +162,22 @@ endmacro()
 # - HAVE_SDL_LOADSO opt
 macro(CheckPulseAudio)
   if(SDL_PULSEAUDIO)
-    pkg_check_modules(PKG_PULSEAUDIO libpulse>=5.0)
-    if(PKG_PULSEAUDIO_FOUND)
+    set(PulseAudio_PKG_CONFIG_SPEC "libpulse>=5.0")
+    pkg_check_modules(PC_PULSEAUDIO IMPORTED_TARGET ${PulseAudio_PKG_CONFIG_SPEC})
+    if(PC_PULSEAUDIO_FOUND)
       set(HAVE_PULSEAUDIO TRUE)
-      file(GLOB PULSEAUDIO_SOURCES ${SDL3_SOURCE_DIR}/src/audio/pulseaudio/*.c)
-      list(APPEND SOURCE_FILES ${PULSEAUDIO_SOURCES})
+      sdl_glob_sources("${SDL3_SOURCE_DIR}/src/audio/pulseaudio/*.c")
       set(SDL_AUDIO_DRIVER_PULSEAUDIO 1)
-      target_include_directories(sdl-build-options SYSTEM INTERFACE ${PKG_PULSEAUDIO_INCLUDE_DIRS})
       if(SDL_PULSEAUDIO_SHARED AND NOT HAVE_SDL_LOADSO)
-        message_warn("You must have SDL_LoadObject() support for dynamic PulseAudio loading")
+        message(WARNING "You must have SDL_LoadObject() support for dynamic PulseAudio loading")
       endif()
-      FindLibraryAndSONAME("pulse" LIBDIRS ${PKG_PULSEAUDIO_LIBRARY_DIRS})
+      FindLibraryAndSONAME("pulse" LIBDIRS ${PC_PULSEAUDIO_LIBRARY_DIRS})
       if(SDL_PULSEAUDIO_SHARED AND PULSE_LIB AND HAVE_SDL_LOADSO)
         set(SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC "\"${PULSE_LIB_SONAME}\"")
         set(HAVE_PULSEAUDIO_SHARED TRUE)
+        sdl_link_dependency(pulseaudio INCLUDES $<TARGET_PROPERTY:PkgConfig::PC_PULSEAUDIO,INTERFACE_INCLUDE_DIRECTORIES>)
       else()
-        list(APPEND SDL_EXTRA_LDFLAGS ${PKG_PULSEAUDIO_LDFLAGS})
+        sdl_link_dependency(pulseaudio LIBS PkgConfig::PC_PULSEAUDIO PKG_CONFIG_PREFIX PC_PULSEAUDIO PKG_CONFIG_SPECS "${PulseAudio_PKG_CONFIG_SPEC}")
       endif()
       set(HAVE_SDL_AUDIO TRUE)
     endif()
@@ -189,22 +191,22 @@ endmacro()
 # - HAVE_SDL_LOADSO opt
 macro(CheckJACK)
   if(SDL_JACK)
-    pkg_check_modules(PKG_JACK jack)
-    if(PKG_JACK_FOUND)
+    set(Jack_PKG_CONFIG_SPEC jack)
+    pkg_check_modules(PC_JACK IMPORTED_TARGET ${Jack_PKG_CONFIG_SPEC})
+    if(PC_JACK_FOUND)
       set(HAVE_JACK TRUE)
-      file(GLOB JACK_SOURCES ${SDL3_SOURCE_DIR}/src/audio/jack/*.c)
-      list(APPEND SOURCE_FILES ${JACK_SOURCES})
+      sdl_glob_sources("${SDL3_SOURCE_DIR}/src/audio/jack/*.c")
       set(SDL_AUDIO_DRIVER_JACK 1)
-      target_include_directories(sdl-build-options SYSTEM INTERFACE ${PKG_JACK_INCLUDE_DIRS})
       if(SDL_JACK_SHARED AND NOT HAVE_SDL_LOADSO)
-        message_warn("You must have SDL_LoadObject() support for dynamic JACK audio loading")
+        message(WARNING "You must have SDL_LoadObject() support for dynamic JACK audio loading")
       endif()
-      FindLibraryAndSONAME("jack" LIBDIRS ${PKG_JACK_LIBRARY_DIRS})
+      FindLibraryAndSONAME("jack" LIBDIRS ${PC_JACK_LIBRARY_DIRS})
       if(SDL_JACK_SHARED AND JACK_LIB AND HAVE_SDL_LOADSO)
         set(SDL_AUDIO_DRIVER_JACK_DYNAMIC "\"${JACK_LIB_SONAME}\"")
         set(HAVE_JACK_SHARED TRUE)
+        sdl_link_dependency(jack INCLUDES $<TARGET_PROPERTY:PkgConfig::PC_JACK,INTERFACE_INCLUDE_DIRECTORIES>)
       else()
-        list(APPEND SDL_EXTRA_LDFLAGS ${PKG_JACK_LDFLAGS})
+        sdl_link_dependency(jack LIBS PkgConfig::PC_JACK PKG_CONFIG_PREFIX PC_JACK PKG_CONFIG_SPECS ${Jack_PKG_CONFIG_SPEC})
       endif()
       set(HAVE_SDL_AUDIO TRUE)
     endif()
@@ -218,22 +220,22 @@ endmacro()
 # - HAVE_SDL_LOADSO opt
 macro(CheckSNDIO)
   if(SDL_SNDIO)
-    pkg_check_modules(PKG_SNDIO sndio)
-    if(PKG_SNDIO_FOUND)
+    set(SndIO_PKG_CONFIG_SPEC sndio)
+    pkg_check_modules(PC_SNDIO IMPORTED_TARGET ${SndIO_PKG_CONFIG_SPEC})
+    if(PC_SNDIO_FOUND)
       set(HAVE_SNDIO TRUE)
-      file(GLOB SNDIO_SOURCES ${SDL3_SOURCE_DIR}/src/audio/sndio/*.c)
-      list(APPEND SOURCE_FILES ${SNDIO_SOURCES})
+      sdl_glob_sources("${SDL3_SOURCE_DIR}/src/audio/sndio/*.c")
       set(SDL_AUDIO_DRIVER_SNDIO 1)
-      target_include_directories(sdl-build-options INTERFACE ${PKG_SNDIO_INCLUDE_DIRS})
       if(SDL_SNDIO_SHARED AND NOT HAVE_SDL_LOADSO)
-        message_warn("You must have SDL_LoadObject() support for dynamic sndio loading")
+        message(WARNING "You must have SDL_LoadObject() support for dynamic sndio loading")
       endif()
-      FindLibraryAndSONAME("sndio" LIBDIRS ${PKG_SNDIO_LIBRARY_DIRS})
+      FindLibraryAndSONAME("sndio" LIBDIRS ${PC_SNDIO_LIBRARY_DIRS})
       if(SDL_SNDIO_SHARED AND SNDIO_LIB AND HAVE_SDL_LOADSO)
         set(SDL_AUDIO_DRIVER_SNDIO_DYNAMIC "\"${SNDIO_LIB_SONAME}\"")
         set(HAVE_SNDIO_SHARED TRUE)
+        sdl_include_directories(PRIVATE SYSTEM $<TARGET_PROPERTY:PkgConfig::PC_SNDIO,INTERFACE_INCLUDE_DIRECTORIES>)
       else()
-        list(APPEND SDL_EXTRA_LIBS ${PKG_SNDIO_LDFLAGS})
+        sdl_link_dependency(sndio LIBS PkgConfig::PC_SNDIO PKG_CONFIG_PREFIX PC_SNDIO PKG_CONFIG_SPECS ${SndIO_PKG_CONFIG_SPEC})
       endif()
       set(HAVE_SDL_AUDIO TRUE)
     endif()
@@ -248,14 +250,26 @@ endmacro()
 macro(CheckX11)
   cmake_push_check_state()
   if(SDL_X11)
+    set(X11_PKG_CONFIG_SPEC x11)
+    set(Xext_PKG_CONFIG_SPEC xext)
+    set(Xcursor_PKG_CONFIG_SPEC xcursor)
+    set(Xi_PKG_CONFIG_SPEC xi)
+    set(Xfixes_PKG_CONFIG_SPEC xfixes)
+    set(Xrandr_PKG_CONFIG_SPEC xrandr)
+    set(Xrender_PKG_CONFIG_SPEC xrender)
+    set(Xss_PKG_CONFIG_SPEC xscrnsaver)
+
+    find_package(X11)
+
     foreach(_LIB X11 Xext Xcursor Xi Xfixes Xrandr Xrender Xss)
-        FindLibraryAndSONAME("${_LIB}")
+      get_filename_component(_libdir "${X11_${_LIB}_LIB}" DIRECTORY)
+      FindLibraryAndSONAME("${_LIB}" LIBDIRS ${_libdir})
     endforeach()
 
-    set(X11_dirs)
-    find_path(X_INCLUDEDIR
+    find_path(X11_INCLUDEDIR
       NAMES X11/Xlib.h
       PATHS
+        ${X11_INCLUDE_DIR}
         /usr/pkg/xorg/include
         /usr/X11R6/include
         /usr/X11R7/include
@@ -267,31 +281,30 @@ macro(CheckX11)
         /opt/X11/include
     )
 
-    if(X_INCLUDEDIR)
-      target_include_directories(sdl-build-options INTERFACE "${X_INCLUDEDIR}")
-      list(APPEND CMAKE_REQUIRED_INCLUDES ${X_INCLUDEDIR})
+    if(X11_INCLUDEDIR)
+      sdl_include_directories(PRIVATE SYSTEM "${X11_INCLUDEDIR}")
+      list(APPEND CMAKE_REQUIRED_INCLUDES ${X11_INCLUDEDIR})
     endif()
 
-    find_file(HAVE_XCURSOR_H NAMES "X11/Xcursor/Xcursor.h" HINTS "${X_INCLUDEDIR}")
-    find_file(HAVE_XINPUT2_H NAMES "X11/extensions/XInput2.h" HINTS "${X_INCLUDEDIR}")
-    find_file(HAVE_XRANDR_H NAMES "X11/extensions/Xrandr.h" HINTS "${X_INCLUDEDIR}")
-    find_file(HAVE_XFIXES_H_ NAMES "X11/extensions/Xfixes.h" HINTS "${X_INCLUDEDIR}")
-    find_file(HAVE_XRENDER_H NAMES "X11/extensions/Xrender.h" HINTS "${X_INCLUDEDIR}")
-    find_file(HAVE_XSS_H NAMES "X11/extensions/scrnsaver.h" HINTS "${X_INCLUDEDIR}")
-    find_file(HAVE_XSHAPE_H NAMES "X11/extensions/shape.h" HINTS "${X_INCLUDEDIR}")
-    find_file(HAVE_XDBE_H NAMES "X11/extensions/Xdbe.h" HINTS "${X_INCLUDEDIR}")
-    find_file(HAVE_XEXT_H NAMES "X11/extensions/Xext.h" HINTS "${X_INCLUDEDIR}")
+    find_file(HAVE_XCURSOR_H NAMES "X11/Xcursor/Xcursor.h" HINTS "${X11_INCLUDEDIR}")
+    find_file(HAVE_XINPUT2_H NAMES "X11/extensions/XInput2.h" HINTS "${X11_INCLUDEDIR}")
+    find_file(HAVE_XRANDR_H NAMES "X11/extensions/Xrandr.h" HINTS "${X11_INCLUDEDIR}")
+    find_file(HAVE_XFIXES_H_ NAMES "X11/extensions/Xfixes.h" HINTS "${X11_INCLUDEDIR}")
+    find_file(HAVE_XRENDER_H NAMES "X11/extensions/Xrender.h" HINTS "${X11_INCLUDEDIR}")
+    find_file(HAVE_XSS_H NAMES "X11/extensions/scrnsaver.h" HINTS "${X11_INCLUDEDIR}")
+    find_file(HAVE_XSHAPE_H NAMES "X11/extensions/shape.h" HINTS "${X11_INCLUDEDIR}")
+    find_file(HAVE_XDBE_H NAMES "X11/extensions/Xdbe.h" HINTS "${X11_INCLUDEDIR}")
+    find_file(HAVE_XEXT_H NAMES "X11/extensions/Xext.h" HINTS "${X11_INCLUDEDIR}")
 
     if(X11_LIB)
       if(NOT HAVE_XEXT_H)
-        message_error("Missing Xext.h, maybe you need to install the libxext-dev package?")
+        message(FATAL_ERROR "Missing Xext.h, maybe you need to install the libxext-dev package?")
       endif()
 
       set(HAVE_X11 TRUE)
       set(HAVE_SDL_VIDEO TRUE)
 
-      file(GLOB X11_SOURCES ${SDL3_SOURCE_DIR}/src/video/x11/*.c)
-      list(APPEND SOURCE_FILES ${X11_SOURCES})
+      sdl_glob_sources("${SDL3_SOURCE_DIR}/src/video/x11/*.c")
       set(SDL_VIDEO_DRIVER_X11 1)
 
       # !!! FIXME: why is this disabled for Apple?
@@ -303,16 +316,16 @@ macro(CheckX11)
       if(NOT HAVE_SHMAT_IN_LIBC)
         check_library_exists(ipc shmat "" HAVE_SHMAT_IN_LIBIPC)
         if(HAVE_SHMAT_IN_LIBIPC)
-          list(APPEND SDL_EXTRA_LIBS ipc)
+          sdl_link_dependency(x11_ipc LIBS ipc)
         endif()
         if(NOT HAVE_SHMAT_IN_LIBIPC)
-          target_compile_definitions(sdl-build-options INTERFACE "NO_SHARED_MEMORY")
+          sdl_compile_definitions(PRIVATE "NO_SHARED_MEMORY")
         endif()
       endif()
 
       if(SDL_X11_SHARED)
         if(NOT HAVE_SDL_LOADSO)
-          message_warn("You must have SDL_LoadObject() support for dynamic X11 loading")
+          message(WARNING "You must have SDL_LoadObject() support for dynamic X11 loading")
           set(HAVE_X11_SHARED FALSE)
         else()
           set(HAVE_X11_SHARED TRUE)
@@ -321,21 +334,19 @@ macro(CheckX11)
           if(HAVE_X11_SHARED)
             set(SDL_VIDEO_DRIVER_X11_DYNAMIC "\"${X11_LIB_SONAME}\"")
           else()
-            list(APPEND SDL_EXTRA_LDFLAGS "-L${X11_LIBDIR}")
-            list(APPEND SDL_EXTRA_LIBS X11)
+            sdl_link_dependency(x11 LIBS X11::X11 CMAKE_MODULE X11 PKG_CONFIG_SPECS ${X11_PKG_CONFIG_SPEC})
           endif()
         endif()
         if(XEXT_LIB)
           if(HAVE_X11_SHARED)
             set(SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT "\"${XEXT_LIB_SONAME}\"")
           else()
-            list(APPEND SDL_EXTRA_LDFLAGS "-L${XEXT_LIBDIR}")
-            list(APPEND SDL_EXTRA_LIBS Xext)
+            sdl_link_dependency(xext LIBS X11::Xext CMAKE_MODULE X11 PKG_CONFIG_SPECS ${Xext_PKG_CONFIG_SPEC})
           endif()
         endif()
       else()
-          list(APPEND SDL_EXTRA_LDFLAGS "-L${X11_LIBDIR}" "-L${XEXT_LIBDIR}")
-          list(APPEND SDL_EXTRA_LIBS X11 Xext)
+        sdl_link_dependency(x11 LIBS X11::X11 CMAKE_MODULE X11 PKG_CONFIG_SPECS ${X11_PKG_CONFIG_SPEC})
+        sdl_link_dependency(xext LIBS X11::Xext CMAKE_MODULE X11 PKG_CONFIG_SPECS ${Xext_PKG_CONFIG_SPEC})
       endif()
 
       list(APPEND CMAKE_REQUIRED_LIBRARIES ${X11_LIB})
@@ -361,8 +372,7 @@ macro(CheckX11)
         if(HAVE_X11_SHARED)
           set(SDL_VIDEO_DRIVER_X11_DYNAMIC_XCURSOR "\"${XCURSOR_LIB_SONAME}\"")
         else()
-          list(APPEND SDL_EXTRA_LDFLAGS "-L${XCURSOR_LIBDIR}")
-          list(APPEND SDL_EXTRA_LIBS Xcursor)
+          sdl_link_dependency(xcursor LIBS X11::Xcursor CMAKE_MODULE X11 PKG_CONFIG_SPECS ${Xcursor_PKG_CONFIG_SPEC})
         endif()
         set(SDL_VIDEO_DRIVER_X11_XCURSOR 1)
       endif()
@@ -377,8 +387,7 @@ macro(CheckX11)
         if(HAVE_X11_SHARED)
           set(SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2 "\"${XI_LIB_SONAME}\"")
         else()
-          list(APPEND SDL_EXTRA_LDFLAGS "-L${XI_LIBDIR}")
-          list(APPEND SDL_EXTRA_LIBS Xi)
+          sdl_link_dependency(xi LIBS X11::Xi CMAKE_MODULE X11 PKG_CONFIG_SPECS ${Xi_PKG_CONFIG_SPEC})
         endif()
         set(SDL_VIDEO_DRIVER_X11_XINPUT2 1)
 
@@ -412,8 +421,7 @@ macro(CheckX11)
         if(HAVE_X11_SHARED)
           set(SDL_VIDEO_DRIVER_X11_DYNAMIC_XFIXES "\"${XFIXES_LIB_SONAME}\"")
         else()
-          list(APPEND SDL_EXTRA_LDFLAGS "-L${XFIXES_LIBDIR}")
-          list(APPEND SDL_EXTRA_LIBS Xfixes)
+          sdl_link_dependency(xfixes LIBS X11::Xfixes CMAKE_MODULE X11 PKG_CONFIG_SPECS ${Xfixes_PKG_CONFIG_SPEC})
         endif()
         set(SDL_VIDEO_DRIVER_X11_XFIXES 1)
         set(HAVE_X11_XFIXES TRUE)
@@ -423,8 +431,7 @@ macro(CheckX11)
         if(HAVE_X11_SHARED)
           set(SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR "\"${XRANDR_LIB_SONAME}\"")
         else()
-          list(APPEND SDL_EXTRA_LDFLAGS "-L${XRANDR_LIBDIR}")
-          list(APPEND SDL_EXTRA_LIBS Xrandr)
+          sdl_link_dependency(xrandr LIBS X11::Xrandr CMAKE_MODULE X11 PKG_CONFIG_SPECS ${Xrandr_PKG_CONFIG_SPEC})
         endif()
         set(SDL_VIDEO_DRIVER_X11_XRANDR 1)
         set(HAVE_X11_XRANDR TRUE)
@@ -434,8 +441,7 @@ macro(CheckX11)
         if(HAVE_X11_SHARED)
           set(SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS "\"${XSS_LIB_SONAME}\"")
         else()
-          list(APPEND SDL_EXTRA_LDFLAGS "-L${XSS_LIBDIR}")
-          list(APPEND SDL_EXTRA_LIBS Xss)
+          sdl_link_dependency(xss LIBS X11::Xss CMAKE_MODULE X11 PKG_CONFIG_SPECS ${Xss_PKG_CONFIG_SPEC})
         endif()
         set(SDL_VIDEO_DRIVER_X11_XSCRNSAVER 1)
         set(HAVE_X11_XSCRNSAVER TRUE)
@@ -449,7 +455,7 @@ macro(CheckX11)
   endif()
   if(NOT HAVE_X11)
     # Prevent Mesa from including X11 headers
-    target_compile_definitions(sdl-build-options INTERFACE "MESA_EGL_NO_X11_HEADERS" "EGL_NO_X11")
+    sdl_compile_definitions(PRIVATE "MESA_EGL_NO_X11_HEADERS" "EGL_NO_X11")
   endif()
   cmake_pop_check_state()
 endmacro()
@@ -472,8 +478,7 @@ macro(WaylandProtocolGen _SCANNER _CODE_MODE _XML _PROTL)
         ARGS "${_CODE_MODE}" "${_XML}" "${_WAYLAND_PROT_C_CODE}"
     )
 
-    list(APPEND SDL_GENERATED_HEADERS "${_WAYLAND_PROT_H_CODE}")
-    list(APPEND SOURCE_FILES "${_WAYLAND_PROT_C_CODE}")
+    sdl_sources("${_WAYLAND_PROT_C_CODE}")
 endmacro()
 
 # Requires:
@@ -484,97 +489,95 @@ endmacro()
 # - HAVE_SDL_LOADSO opt
 macro(CheckWayland)
   if(SDL_WAYLAND)
-    set(WAYLAND_FOUND FALSE)
-    pkg_check_modules(PKG_WAYLAND "wayland-client>=1.18" wayland-egl wayland-cursor egl "xkbcommon>=0.5.0")
+    set(WAYLAND_PKG_CONFIG_SPEC "wayland-client>=1.18" wayland-egl wayland-cursor egl "xkbcommon>=0.5.0")
+    pkg_check_modules(PC_WAYLAND IMPORTED_TARGET ${WAYLAND_PKG_CONFIG_SPEC})
+    find_program(WAYLAND_SCANNER NAMES wayland-scanner)
 
-    if(PKG_WAYLAND_FOUND)
-      set(WAYLAND_FOUND TRUE)
-      find_program(WAYLAND_SCANNER NAMES wayland-scanner REQUIRED)
+    set(WAYLAND_FOUND FALSE)
+    if(PC_WAYLAND_FOUND AND WAYLAND_SCANNER)
       execute_process(
         COMMAND ${WAYLAND_SCANNER} --version
         RESULT_VARIABLE WAYLAND_SCANNER_VERSION_RC
-        ERROR_VARIABLE WAYLAND_SCANNER_VERSION
+        ERROR_VARIABLE WAYLAND_SCANNER_VERSION_STDERR
         ERROR_STRIP_TRAILING_WHITESPACE
       )
       if(NOT WAYLAND_SCANNER_VERSION_RC EQUAL 0)
-        message(FATAL "Failed to get wayland-scanner version")
-        set(WAYLAND_FOUND FALSE)
-      endif()
-      string(REPLACE "wayland-scanner " "" WAYLAND_SCANNER_VERSION ${WAYLAND_SCANNER_VERSION})
-
-      string(COMPARE LESS ${WAYLAND_SCANNER_VERSION} "1.15.0" WAYLAND_SCANNER_PRE_1_15)
-      if(WAYLAND_SCANNER_PRE_1_15)
-        set(WAYLAND_SCANNER_CODE_MODE "code")
+        message(WARNING "Failed to get wayland-scanner version")
       else()
-        set(WAYLAND_SCANNER_CODE_MODE "private-code")
+        if(WAYLAND_SCANNER_VERSION_STDERR MATCHES [[([0-9.]+)$]])
+          set(WAYLAND_FOUND TRUE)
+          set(WAYLAND_SCANNER_VERSION ${CMAKE_MATCH_1})
+          if(WAYLAND_SCANNER_VERSION VERSION_LESS "1.15.0")
+            set(WAYLAND_SCANNER_CODE_MODE "code")
+          else()
+            set(WAYLAND_SCANNER_CODE_MODE "private-code")
+          endif()
+        endif()
       endif()
     endif()
 
     if(WAYLAND_FOUND)
-      target_link_directories(sdl-build-options INTERFACE ${PKG_WAYLAND_LIBRARY_DIRS})
-      target_include_directories(sdl-build-options INTERFACE ${PKG_WAYLAND_INCLUDE_DIRS})
-
       set(HAVE_WAYLAND TRUE)
       set(HAVE_SDL_VIDEO TRUE)
 
-      file(GLOB WAYLAND_SOURCES ${SDL3_SOURCE_DIR}/src/video/wayland/*.c)
-      list(APPEND SOURCE_FILES ${WAYLAND_SOURCES})
+      sdl_glob_sources("${SDL3_SOURCE_DIR}/src/video/wayland/*.c")
 
       # We have to generate some protocol interface code for some unstable Wayland features.
-      file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/wayland-generated-protocols")
-      # Prepend to include path to make sure it they override installed protocol headers
-      target_include_directories(sdl-build-options SYSTEM BEFORE INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/wayland-generated-protocols")
+      file(MAKE_DIRECTORY "${SDL3_BINARY_DIR}/wayland-generated-protocols")
+      # Prepend to include path to make sure they override installed protocol headers
+      sdl_include_directories(PRIVATE SYSTEM BEFORE "${SDL3_BINARY_DIR}/wayland-generated-protocols")
 
       file(GLOB WAYLAND_PROTOCOLS_XML RELATIVE "${SDL3_SOURCE_DIR}/wayland-protocols/" "${SDL3_SOURCE_DIR}/wayland-protocols/*.xml")
-      foreach(_XML ${WAYLAND_PROTOCOLS_XML})
+      foreach(_XML IN LISTS WAYLAND_PROTOCOLS_XML)
         string(REGEX REPLACE "\\.xml$" "" _PROTL "${_XML}")
         WaylandProtocolGen("${WAYLAND_SCANNER}" "${WAYLAND_SCANNER_CODE_MODE}" "${SDL3_SOURCE_DIR}/wayland-protocols/${_XML}" "${_PROTL}")
       endforeach()
 
       if(SDL_WAYLAND_QT_TOUCH)
-          set(HAVE_WAYLAND_QT_TOUCH TRUE)
-          set(SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH 1)
+        set(HAVE_WAYLAND_QT_TOUCH TRUE)
+        set(SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH 1)
       endif()
 
       if(SDL_WAYLAND_SHARED AND NOT HAVE_SDL_LOADSO)
-        message_warn("You must have SDL_LoadObject() support for dynamic Wayland loading")
+        message(WARNING "You must have SDL_LoadObject() support for dynamic Wayland loading")
       endif()
-      FindLibraryAndSONAME(wayland-client LIBDIRS ${PKG_WAYLAND_LIBRARY_DIRS})
-      FindLibraryAndSONAME(wayland-egl LIBDIRS ${PKG_WAYLAND_LIBRARY_DIRS})
-      FindLibraryAndSONAME(wayland-cursor LIBDIRS ${PKG_WAYLAND_LIBRARY_DIRS})
-      FindLibraryAndSONAME(xkbcommon LIBDIRS ${PKG_WAYLAND_LIBRARY_DIRS})
+      FindLibraryAndSONAME(wayland-client LIBDIRS ${PC_WAYLAND_LIBRARY_DIRS})
+      FindLibraryAndSONAME(wayland-egl LIBDIRS ${PC_WAYLAND_LIBRARY_DIRS})
+      FindLibraryAndSONAME(wayland-cursor LIBDIRS ${PC_WAYLAND_LIBRARY_DIRS})
+      FindLibraryAndSONAME(xkbcommon LIBDIRS ${PC_WAYLAND_LIBRARY_DIRS})
       if(SDL_WAYLAND_SHARED AND WAYLAND_CLIENT_LIB AND WAYLAND_EGL_LIB AND WAYLAND_CURSOR_LIB AND XKBCOMMON_LIB AND HAVE_SDL_LOADSO)
         set(SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC "\"${WAYLAND_CLIENT_LIB_SONAME}\"")
         set(SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL "\"${WAYLAND_EGL_LIB_SONAME}\"")
         set(SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR "\"${WAYLAND_CURSOR_LIB_SONAME}\"")
         set(SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON "\"${XKBCOMMON_LIB_SONAME}\"")
         set(HAVE_WAYLAND_SHARED TRUE)
+        sdl_link_dependency(wayland INCLUDES $<TARGET_PROPERTY:PkgConfig::PC_WAYLAND,INTERFACE_INCLUDE_DIRECTORIES>)
       else()
-        list(APPEND SDL_EXTRA_LIBS ${PKG_WAYLAND_LIBRARIES})
+        sdl_link_dependency(wayland LIBS PkgConfig::PC_WAYLAND PKG_CONFIG_PREFIX PC_WAYLAND PKG_CONFIG_SPECS ${WAYLAND_PKG_CONFIG_SPEC})
       endif()
 
       if(SDL_WAYLAND_LIBDECOR)
-        pkg_check_modules(PKG_LIBDECOR libdecor-0)
-        if(PKG_LIBDECOR_FOUND)
-            set(HAVE_WAYLAND_LIBDECOR TRUE)
-            set(HAVE_LIBDECOR_H 1)
-            target_link_directories(sdl-build-options INTERFACE "${PKG_LIBDECOR_LIBRARY_DIRS}")
-            target_include_directories(sdl-build-options SYSTEM INTERFACE "${PKG_LIBDECOR_INCLUDE_DIRS}")
-            if(SDL_WAYLAND_LIBDECOR_SHARED AND NOT HAVE_SDL_LOADSO)
-                message_warn("You must have SDL_LoadObject() support for dynamic libdecor loading")
-            endif()
-            FindLibraryAndSONAME(decor-0 LIBDIRS ${PKG_LIBDECOR_LIBRARY_DIRS})
-            if(SDL_WAYLAND_LIBDECOR_SHARED AND DECOR_0_LIB AND HAVE_SDL_LOADSO)
-                set(HAVE_WAYLAND_LIBDECOR_SHARED TRUE)
-                set(SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECOR "\"${DECOR_0_LIB_SONAME}\"")
-            else()
-              list(APPEND SDL_EXTRA_LIBS ${PKG_LIBDECOR_LIBRARIES})
+        set(LibDecor_PKG_CONFIG_SPEC libdecor-0)
+        pkg_check_modules(PC_LIBDECOR IMPORTED_TARGET ${LibDecor_PKG_CONFIG_SPEC})
+        if(PC_LIBDECOR_FOUND)
+          # Version 0.1.2 or higher is needed for suspended window state and statically linked min/max getters.
+          if(PC_LIBDECOR_VERSION VERSION_GREATER_EQUAL "0.1.2")
+            set(SDL_HAVE_LIBDECOR_VER_0_1_2 1)
+            set(LibDecor_PKG_CONFIG_SPEC "libdecor-0>=0.1.2")
+          endif()
+          set(HAVE_WAYLAND_LIBDECOR TRUE)
+          set(HAVE_LIBDECOR_H 1)
+          if(SDL_WAYLAND_LIBDECOR_SHARED AND NOT HAVE_SDL_LOADSO)
+            message(WARNING "You must have SDL_LoadObject() support for dynamic libdecor loading")
+          endif()
+          FindLibraryAndSONAME(decor-0 LIBDIRS ${PC_LIBDECOR_LIBRARY_DIRS})
+          if(SDL_WAYLAND_LIBDECOR_SHARED AND DECOR_0_LIB AND HAVE_SDL_LOADSO)
+            set(HAVE_WAYLAND_LIBDECOR_SHARED TRUE)
+            set(SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECOR "\"${DECOR_0_LIB_SONAME}\"")
+            sdl_link_dependency(libdecor INCLUDES $<TARGET_PROPERTY:PkgConfig::PC_LIBDECOR,INTERFACE_INCLUDE_DIRECTORIES>)
+          else()
+            sdl_link_dependency(libdecor LIBS PkgConfig::PC_LIBDECOR PKG_CONFIG_PREFIX PC_LIBDECOR PKG_CONFIG_SPECS ${LibDecor_PKG_CONFIG_SPEC})
             endif()
-
-            # Version 0.1.2 or higher is needed for suspended window state and statically linked min/max getters.
-            if (PKG_LIBDECOR_VERSION VERSION_GREATER_EQUAL "0.1.2")
-              set(SDL_HAVE_LIBDECOR_VER_0_1_2 1)
-            endif ()
         endif()
       endif()
 
@@ -592,8 +595,7 @@ macro(CheckCOCOA)
       set(HAVE_COCOA TRUE)
     endif()
     if(HAVE_COCOA)
-      file(GLOB COCOA_SOURCES ${SDL3_SOURCE_DIR}/src/video/cocoa/*.m)
-      list(APPEND SOURCE_FILES ${COCOA_SOURCES})
+      sdl_glob_sources("${SDL3_SOURCE_DIR}/src/video/cocoa/*.m")
       set(SDL_VIDEO_DRIVER_COCOA 1)
       set(HAVE_SDL_VIDEO TRUE)
     endif()
@@ -616,18 +618,18 @@ macro(CheckVivante)
       set(HAVE_VIVANTE TRUE)
       set(HAVE_SDL_VIDEO TRUE)
 
-      file(GLOB VIVANTE_SOURCES ${SDL3_SOURCE_DIR}/src/video/vivante/*.c)
-      list(APPEND SOURCE_FILES ${VIVANTE_SOURCES})
+      sdl_glob_sources("${SDL3_SOURCE_DIR}/src/video/vivante/*.c")
       set(SDL_VIDEO_DRIVER_VIVANTE 1)
+      # FIXME: Use Find module
       if(HAVE_VIVANTE_VDK)
         set(SDL_VIDEO_DRIVER_VIVANTE_VDK 1)
         find_library(VIVANTE_LIBRARY REQUIRED NAMES VIVANTE vivante drm_vivante)
         find_library(VIVANTE_VDK_LIBRARY VDK REQUIRED)
-        list(APPEND SDL_EXTRA_LIBS ${VIVANTE_LIBRARY} ${VIVANTE_VDK_LIBRARY})
+        sdl_link_dependency(vivante LIBS ${VIVANTE_LIBRARY} ${VIVANTE_VDK_LIBRARY})
       else()
-        target_compile_definitions(sdl-build-options INTERFACE "LINUX;EGL_API_FB")
-        list(APPEND SDL_PC_CFLAGS -DLINUX -DEGL_API_FB)
-        list(APPEND SDL_EXTRA_LIBS EGL)
+        # these defines are needed when including the system EGL headers, which SDL does
+        sdl_compile_definitions(PUBLIC "LINUX" "EGL_API_FB")
+        sdl_link_dependency(vivante LIBS EGL)
       endif(HAVE_VIVANTE_VDK)
     endif()
   endif()
@@ -649,9 +651,10 @@ endmacro()
 # Requires:
 # - PkgCheckModules
 macro(CheckEGL)
-  if (SDL_OPENGL OR SDL_OPENGLES)
-    pkg_check_modules(EGL egl)
-    set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} ${EGL_CFLAGS}")
+  if(SDL_OPENGL OR SDL_OPENGLES)
+    cmake_push_check_state()
+    find_package(OpenGL MODULE)
+    list(APPEND CMAKE_REQUIRED_INCLUDES ${OPENGL_EGL_INCLUDE_DIRS})
     check_c_source_compiles("
         #define EGL_API_FB
         #define MESA_EGL_NO_X11_HEADERS
@@ -659,8 +662,10 @@ macro(CheckEGL)
         #include <EGL/egl.h>
         #include <EGL/eglext.h>
         int main (int argc, char** argv) { return 0; }" HAVE_OPENGL_EGL)
+    cmake_pop_check_state()
     if(HAVE_OPENGL_EGL)
       set(SDL_VIDEO_OPENGL_EGL 1)
+      sdl_link_dependency(egl INCLUDES ${OPENGL_EGL_INCLUDE_DIRS})
     endif()
   endif()
 endmacro()
@@ -689,21 +694,28 @@ macro(CheckOpenGLES)
         #include <GLES/glext.h>
         int main (int argc, char** argv) { return 0; }" HAVE_OPENGLES_V1)
     if(HAVE_OPENGLES_V1)
-        set(HAVE_OPENGLES TRUE)
-        set(SDL_VIDEO_OPENGL_ES 1)
+      set(HAVE_OPENGLES TRUE)
+      set(SDL_VIDEO_OPENGL_ES 1)
     endif()
     check_c_source_compiles("
-        #include <GLES2/gl2.h>
-        #include <GLES2/gl2ext.h>
-        int main (int argc, char** argv) { return 0; }" HAVE_OPENGLES_V2)
+      #include <GLES2/gl2.h>
+      #include <GLES2/gl2ext.h>
+      int main (int argc, char** argv) { return 0; }" HAVE_OPENGLES_V2)
     if(HAVE_OPENGLES_V2)
-        set(HAVE_OPENGLES TRUE)
-        set(SDL_VIDEO_OPENGL_ES2 1)
-        set(SDL_VIDEO_RENDER_OGL_ES2 1)
+      set(HAVE_OPENGLES TRUE)
+      set(SDL_VIDEO_OPENGL_ES2 1)
+      set(SDL_VIDEO_RENDER_OGL_ES2 1)
     endif()
   endif()
 endmacro()
 
+macro(CheckVulkan)
+  if(SDL_VULKAN)
+    set(SDL_VIDEO_VULKAN 1)
+    set(HAVE_VULKAN TRUE)
+  endif()
+endmacro()
+
 # Requires:
 # - EGL
 macro(CheckQNXScreen)
@@ -713,9 +725,8 @@ macro(CheckQNXScreen)
         int main (int argc, char** argv) { return 0; }" HAVE_QNX_SCREEN)
     if(HAVE_QNX_SCREEN)
       set(SDL_VIDEO_DRIVER_QNX 1)
-      file(GLOB QNX_VIDEO_SOURCES ${SDL3_SOURCE_DIR}/src/video/qnx/*.c)
-      list(APPEND SOURCE_FILES ${QNX_VIDEO_SOURCES})
-      list(APPEND SDL_EXTRA_LIBS screen EGL)
+      sdl_glob_sources("${SDL3_SOURCE_DIR}/src/video/qnx/*.c")
+      sdl_link_dependency(qnxscreen LIBS screen EGL)
     endif()
   endif()
 endmacro()
@@ -779,20 +790,19 @@ macro(CheckPTHREAD)
     endif()
 
     # Run some tests
-    set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${PTHREAD_CFLAGS} ${PTHREAD_LDFLAGS}")
+    string(APPEND CMAKE_REQUIRED_FLAGS " ${PTHREAD_CFLAGS} ${PTHREAD_LDFLAGS}")
     check_c_source_compiles("
-      #include <pthread.h>
-      int main(int argc, char** argv) {
-        pthread_attr_t type;
-        pthread_attr_init(&type);
-        return 0;
-      }" HAVE_PTHREADS)
+        #include <pthread.h>
+        int main(int argc, char** argv) {
+          pthread_attr_t type;
+          pthread_attr_init(&type);
+          return 0;
+        }" HAVE_PTHREADS)
     if(HAVE_PTHREADS)
       set(SDL_THREAD_PTHREAD 1)
       separate_arguments(PTHREAD_CFLAGS)
-      target_compile_options(sdl-build-options INTERFACE ${PTHREAD_CFLAGS})
-      list(APPEND SDL_EXTRA_LDFLAGS ${PTHREAD_LDFLAGS})
-      list(APPEND SDL_PC_CFLAGS ${PTHREAD_CFLAGS})
+      sdl_compile_options(PRIVATE ${PTHREAD_CFLAGS})
+      sdl_link_dependency(pthread LINK_OPTIONS ${PTHREAD_LDFLAGS})
 
       check_c_source_compiles("
         #include <pthread.h>
@@ -850,19 +860,17 @@ macro(CheckPTHREAD)
         endif()
       endif()
 
-      set(SOURCE_FILES ${SOURCE_FILES}
-          ${SDL3_SOURCE_DIR}/src/thread/pthread/SDL_systhread.c
-          ${SDL3_SOURCE_DIR}/src/thread/pthread/SDL_sysmutex.c   # Can be faked, if necessary
-          ${SDL3_SOURCE_DIR}/src/thread/pthread/SDL_syscond.c    # Can be faked, if necessary
-          ${SDL3_SOURCE_DIR}/src/thread/pthread/SDL_sysrwlock.c   # Can be faked, if necessary
-          ${SDL3_SOURCE_DIR}/src/thread/pthread/SDL_systls.c
-          )
+      sdl_sources(
+        "${SDL3_SOURCE_DIR}/src/thread/pthread/SDL_systhread.c"
+        "${SDL3_SOURCE_DIR}/src/thread/pthread/SDL_sysmutex.c"   # Can be faked, if necessary
+        "${SDL3_SOURCE_DIR}/src/thread/pthread/SDL_syscond.c"    # Can be faked, if necessary
+        "${SDL3_SOURCE_DIR}/src/thread/pthread/SDL_sysrwlock.c"   # Can be faked, if necessary
+        "${SDL3_SOURCE_DIR}/src/thread/pthread/SDL_systls.c"
+      )
       if(HAVE_PTHREADS_SEM)
-        set(SOURCE_FILES ${SOURCE_FILES}
-            ${SDL3_SOURCE_DIR}/src/thread/pthread/SDL_syssem.c)
+        sdl_sources("${SDL3_SOURCE_DIR}/src/thread/pthread/SDL_syssem.c")
       else()
-        set(SOURCE_FILES ${SOURCE_FILES}
-            ${SDL3_SOURCE_DIR}/src/thread/generic/SDL_syssem.c)
+        sdl_sources("${SDL3_SOURCE_DIR}/src/thread/generic/SDL_syssem.c")
       endif()
       set(HAVE_SDL_THREADS TRUE)
     endif()
@@ -887,7 +895,7 @@ macro(CheckUSBHID)
 
     check_include_file(libusbhid.h HAVE_LIBUSBHID_H)
     if(HAVE_LIBUSBHID_H)
-      set(USB_CFLAGS "${USB_CFLAGS} -DHAVE_LIBUSBHID_H")
+      string(APPEND USB_CFLAGS " -DHAVE_LIBUSBHID_H")
     endif()
     set(USB_LIBS ${USB_LIBS} usbhid)
   else()
@@ -897,7 +905,7 @@ macro(CheckUSBHID)
     endif()
     check_include_file(libusb.h HAVE_LIBUSB_H)
     if(HAVE_LIBUSB_H)
-      set(USB_CFLAGS "${USB_CFLAGS} -DHAVE_LIBUSB_H")
+      string(APPEND USB_CFLAGS " -DHAVE_LIBUSB_H")
     endif()
     check_library_exists(usb hid_init "" LIBUSB)
     if(LIBUSB)
@@ -905,7 +913,7 @@ macro(CheckUSBHID)
     endif()
   endif()
 
-  set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${USB_CFLAGS}")
+  string(APPEND CMAKE_REQUIRED_FLAGS " ${USB_CFLAGS}")
   list(APPEND CMAKE_REQUIRED_LIBRARIES ${USB_LIBS})
   check_c_source_compiles("
        #include <sys/types.h>
@@ -958,7 +966,7 @@ macro(CheckUSBHID)
             return 0;
           }" HAVE_USBHID_UCR_DATA)
     if(HAVE_USBHID_UCR_DATA)
-      set(USB_CFLAGS "${USB_CFLAGS} -DUSBHID_UCR_DATA")
+      string(APPEND USB_CFLAGS " -DUSBHID_UCR_DATA")
     endif()
 
     check_c_source_compiles("
@@ -986,7 +994,7 @@ macro(CheckUSBHID)
             return 0;
           }" HAVE_USBHID_NEW)
     if(HAVE_USBHID_NEW)
-      set(USB_CFLAGS "${USB_CFLAGS} -DUSBHID_NEW")
+      string(APPEND USB_CFLAGS " -DUSBHID_NEW")
     endif()
 
     check_c_source_compiles("
@@ -999,13 +1007,12 @@ macro(CheckUSBHID)
       set(SDL_HAVE_MACHINE_JOYSTICK_H 1)
     endif()
     set(SDL_JOYSTICK_USBHID 1)
-    file(GLOB BSD_JOYSTICK_SOURCES ${SDL3_SOURCE_DIR}/src/joystick/bsd/*.c)
-    list(APPEND SOURCE_FILES ${BSD_JOYSTICK_SOURCES})
+    sdl_glob_sources("${SDL3_SOURCE_DIR}/src/joystick/bsd/*.c")
     separate_arguments(USB_CFLAGS)
-    target_compile_options(sdl-build-options INTERFACE ${USB_CFLAGS})
-    list(APPEND SDL_EXTRA_LIBS ${USB_LIBS})
+    sdl_compile_options(PRIVATE ${USB_CFLAGS})
+    #FIXME: properly add usb libs with pkg-config or whatever
+    sdl_link_dependency(usbhid LIBS ${USB_LIBS})
     set(HAVE_SDL_JOYSTICK TRUE)
-
   endif()
   cmake_pop_check_state()
 endmacro()
@@ -1016,20 +1023,25 @@ macro(CheckHIDAPI)
   if(SDL_HIDAPI)
     if(SDL_HIDAPI_LIBUSB)
       set(HAVE_LIBUSB FALSE)
-      pkg_check_modules(PKG_LIBUSB libusb-1.0)
-      if(PKG_LIBUSB_FOUND)
-        check_include_file(libusb.h HAVE_LIBUSB_H ${PKG_LIBUSB_CFLAGS})
+
+      set(LibUSB_PKG_CONFIG_SPEC libusb-1.0)
+      pkg_check_modules(PC_LIBUSB IMPORTED_TARGET ${LibUSB_PKG_CONFIG_SPEC})
+      if(PC_LIBUSB_FOUND)
+        cmake_push_check_state()
+        list(APPEND CMAKE_REQUIRED_INCLUDES ${LibUSB_INCLUDE_DIRS})
+        check_include_file(libusb.h HAVE_LIBUSB_H)
+        cmake_pop_check_state()
         if(HAVE_LIBUSB_H)
           set(HAVE_LIBUSB TRUE)
-          target_include_directories(sdl-build-options SYSTEM INTERFACE ${PKG_LIBUSB_INCLUDE_DIRS})
           if(HIDAPI_ONLY_LIBUSB)
-            list(APPEND SDL_EXTRA_LIBS ${PKG_LIBUSB_LIBRARIES})
+            sdl_link_dependency(hidapi LIBS PkgConfig::PC_LIBUSB PKG_CONFIG_PREFIX PC_LIBUSB PKG_CONFIG_SPECS ${LibUSB_PKG_CONFIG_SPEC})
           else()
-            # libusb is loaded dynamically, so don't add it to SDL_EXTRA_LIBS
-            FindLibraryAndSONAME("usb-1.0" LIBDIRS ${PKG_LIBUSB_LIBRARY_DIRS})
+            # libusb is loaded dynamically, so don't add link to it
+            FindLibraryAndSONAME("usb-1.0" LIBDIRS ${PC_LIBUSB_LIBRARY_DIRS})
             if(USB_1.0_LIB)
               set(SDL_LIBUSB_DYNAMIC "\"${USB_1.0_LIB_SONAME}\"")
             endif()
+            sdl_link_dependency(hidapi INCLUDES $<TARGET_PROPERTY:LibUSB::LibUSB,INTERFACE_INCLUDE_DIRECTORIES>)
           endif()
         endif()
       endif()
@@ -1041,10 +1053,10 @@ macro(CheckHIDAPI)
 
     if(HAVE_HIDAPI)
       if(ANDROID)
-        list(APPEND SOURCE_FILES ${SDL3_SOURCE_DIR}/src/hidapi/android/hid.cpp)
+        sdl_sources("${SDL3_SOURCE_DIR}/src/hidapi/android/hid.cpp")
       endif()
       if(IOS OR TVOS)
-        list(APPEND SOURCE_FILES ${SDL3_SOURCE_DIR}/src/hidapi/ios/hid.m)
+        sdl_sources("${SDL3_SOURCE_DIR}/src/hidapi/ios/hid.m")
         set(SDL_FRAMEWORK_COREBLUETOOTH 1)
       endif()
       set(HAVE_SDL_HIDAPI TRUE)
@@ -1053,8 +1065,7 @@ macro(CheckHIDAPI)
         set(SDL_JOYSTICK_HIDAPI 1)
         set(HAVE_SDL_JOYSTICK TRUE)
         set(HAVE_HIDAPI_JOYSTICK TRUE)
-        file(GLOB HIDAPI_JOYSTICK_SOURCES ${SDL3_SOURCE_DIR}/src/joystick/hidapi/*.c)
-        list(APPEND SOURCE_FILES ${HIDAPI_JOYSTICK_SOURCES})
+        sdl_glob_sources("${SDL3_SOURCE_DIR}/src/joystick/hidapi/*.c")
       endif()
     else()
       set(SDL_HIDAPI_DISABLED 1)
@@ -1068,38 +1079,18 @@ endmacro()
 # - n/a
 macro(CheckRPI)
   if(SDL_RPI)
-    pkg_check_modules(VIDEO_RPI bcm_host brcmegl)
-    if (NOT VIDEO_RPI_FOUND)
-      set(VIDEO_RPI_INCLUDE_DIRS "/opt/vc/include" "/opt/vc/include/interface/vcos/pthreads" "/opt/vc/include/interface/vmcs_host/linux/" )
-      set(VIDEO_RPI_LIBRARY_DIRS "/opt/vc/lib" )
-      set(VIDEO_RPI_LIBRARIES bcm_host )
-      set(VIDEO_RPI_LDFLAGS "-Wl,-rpath,/opt/vc/lib")
-    endif()
-    listtostr(VIDEO_RPI_INCLUDE_DIRS VIDEO_RPI_INCLUDE_FLAGS "-I")
-    separate_arguments(VIDEO_RPI_INCLUDE_FLAGS)
-    listtostr(VIDEO_RPI_LIBRARY_DIRS VIDEO_RPI_LIBRARY_FLAGS "-L")
-    separate_arguments(VIDEO_RPI_LIBRARY_FLAGS)
-
-    cmake_push_check_state()
-    set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${VIDEO_RPI_INCLUDE_FLAGS} ${VIDEO_RPI_LIBRARY_FLAGS}")
-    list(APPEND CMAKE_REQUIRED_LIBRARIES ${VIDEO_RPI_LIBRARIES})
-    check_c_source_compiles("
-        #include <bcm_host.h>
-        #include <EGL/eglplatform.h>
-        int main(int argc, char **argv) {
-          EGL_DISPMANX_WINDOW_T window;
-          bcm_host_init();
-        }" HAVE_RPI)
-    cmake_pop_check_state()
-
-    if(SDL_VIDEO AND HAVE_RPI)
-      set(HAVE_SDL_VIDEO TRUE)
-      set(SDL_VIDEO_DRIVER_RPI 1)
-      file(GLOB VIDEO_RPI_SOURCES ${SDL3_SOURCE_DIR}/src/video/raspberry/*.c)
-      list(APPEND SOURCE_FILES ${VIDEO_RPI_SOURCES})
-      list(APPEND SDL_EXTRA_LIBS ${VIDEO_RPI_LIBRARIES})
-      target_compile_options(sdl-build-options INTERFACE ${VIDEO_RPI_INCLUDE_FLAGS})
-      list(APPEND SDL_EXTRA_LDFLAGS ${VIDEO_RPI_LIBRARY_FLAGS} ${VIDEO_RPI_LDFLAGS})
+    # presence of bcm_host means raspberry pi
+    find_package(RPi_BcmHost)
+    if(RPi_BcmHost_FOUND)
+      set(HAVE_RPI TRUE)
+      sdl_link_dependency(rpi LIBS RPi_BcmHost::RPi_BcmHost CMAKE_MODULE RPi_BcmHost PKG_CONFIG_SPECS ${RPi_BcmHost_PKG_CONFIG_SPEC})
+      find_package(RPi_BrcmEGL)
+      if(SDL_VIDEO AND RPi_BrcmEGL_FOUND)
+        set(HAVE_SDL_VIDEO TRUE)
+        set(SDL_VIDEO_DRIVER_RPI 1)
+        sdl_glob_sources("${SDL3_SOURCE_DIR}/src/video/raspberry/*.c")
+        sdl_link_dependency(rpi-video LIBS RPi_BrcmEGL::RPi_BrcmEGL CMAKE_MODULE RPi_BrcmEGL PKG_CONFIG_SPECS ${RPi_BrcmEGL_PKG_CONFIG_SPEC})
+      endif()
     endif()
   endif()
 endmacro()
@@ -1108,8 +1099,9 @@ endmacro()
 # - n/a
 macro(CheckROCKCHIP)
   if(SDL_ROCKCHIP)
-    pkg_check_modules(VIDEO_ROCKCHIP mali)
-    if (VIDEO_ROCKCHIP_FOUND)
+    set(MALI_PKG_CONFIG_SPEC mali)
+    pkg_check_modules(PC_MALI QUIET ${MALI_PKG_CONFIG_SPEC})
+    if(PC_MALI_FOUND)
       set(HAVE_ROCKCHIP TRUE)
     endif()
     if(SDL_VIDEO AND HAVE_ROCKCHIP)
@@ -1127,31 +1119,36 @@ endmacro()
 # - HAVE_SDL_LOADSO opt
 macro(CheckKMSDRM)
   if(SDL_KMSDRM)
-    pkg_check_modules(PKG_KMSDRM libdrm gbm egl)
-    if(PKG_KMSDRM_FOUND AND HAVE_OPENGL_EGL)
-      target_link_directories(sdl-build-options INTERFACE ${PKG_KMSDRM_LIBRARY_DIRS})
-      target_include_directories(sdl-build-options INTERFACE "${PKG_KMSDRM_INCLUDE_DIRS}")
+    set(PKG_CONFIG_LIBDRM_SPEC libdrm)
+    set(PKG_CONFIG_GBM_SPEC gbm)
+    pkg_check_modules(PC_LIBDRM IMPORTED_TARGET ${PKG_CONFIG_LIBDRM_SPEC})
+    pkg_check_modules(PC_GBM IMPORTED_TARGET ${PKG_CONFIG_GBM_SPEC})
+    if(PC_LIBDRM_FOUND AND PC_GBM_FOUND AND HAVE_OPENGL_EGL)
       set(HAVE_KMSDRM TRUE)
       set(HAVE_SDL_VIDEO TRUE)
 
-      file(GLOB KMSDRM_SOURCES ${SDL3_SOURCE_DIR}/src/video/kmsdrm/*.c)
-      list(APPEND SOURCE_FILES ${KMSDRM_SOURCES})
-
-      target_include_directories(sdl-build-options SYSTEM INTERFACE ${PKG_KMSDRM_INCLUDE_DIRS})
+      sdl_glob_sources("${SDL3_SOURCE_DIR}/src/video/kmsdrm/*.c")
 
       set(SDL_VIDEO_DRIVER_KMSDRM 1)
 
       if(SDL_KMSDRM_SHARED AND NOT HAVE_SDL_LOADSO)
-        message_warn("You must have SDL_LoadObject() support for dynamic KMS/DRM loading")
+        message(WARNING "You must have SDL_LoadObject() support for dynamic KMS/DRM loading")
       endif()
+      set(HAVE_KMSDRM_SHARED FALSE)
       if(SDL_KMSDRM_SHARED AND HAVE_SDL_LOADSO)
-        FindLibraryAndSONAME(drm LIBDIRS ${PKG_KMSDRM_LIBRARY_DIRS})
-        FindLibraryAndSONAME(gbm LIBDIRS ${PKG_KMSDRM_LIBRARY_DIRS})
-        set(SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC "\"${DRM_LIB_SONAME}\"")
-        set(SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM "\"${GBM_LIB_SONAME}\"")
-        set(HAVE_KMSDRM_SHARED TRUE)
-      else()
-        list(APPEND SDL_EXTRA_LIBS ${PKG_KMSDRM_LIBRARIES})
+        FindLibraryAndSONAME(drm LIBDIRS ${PC_LIBDRM_LIBRARY_DIRS})
+        FindLibraryAndSONAME(gbm LIBDIRS ${PC_GBM_LIBRARY_DIRS})
+        if(DRM_LIB AND DRM_SHARED AND GBM_LIB AND GBM_SHARED)
+          set(SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC "\"${DRM_LIB_SONAME}\"")
+          set(SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM "\"${GBM_LIB_SONAME}\"")
+          set(HAVE_KMSDRM_SHARED TRUE)
+          sdl_link_dependency(kmsdrm-drm INCLUDES $<TARGET_PROPERTY:PkgConfig::PC_LIBDRM,INTERFACE_INCLUDE_DIRECTORIES>)
+          sdl_link_dependency(kmsdrm-gbm INCLUDES $<TARGET_PROPERTY:PkgConfig::PC_GBM,INTERFACE_INCLUDE_DIRECTORIES>)
+        endif()
+      endif()
+      if(NOT HAVE_KMSDRM_SHARED)
+        sdl_link_dependency(kmsdrm-libdrm LIBS PkgConfig::PC_LIBDRM PKG_CONFIG_PREFIX PC_LIBDRM PKG_CONFIG_SPECS ${PKG_CONFIG_LIBDRM_SPEC})
+        sdl_link_dependency(kmsdrm-gbm LIBS PkgConfig::PC_GBM PKG_CONFIG_PREFIX PC_GBM PKG_CONFIG_SPECS ${PKG_CONFIG_GBM_SPEC})
       endif()
     endif()
   endif()
@@ -1159,13 +1156,62 @@ endmacro()
 
 macro(CheckLibUDev)
   if(SDL_LIBUDEV)
-    check_include_file("libudev.h" have_libudev_header)
-    if(have_libudev_header)
+    check_include_file("libudev.h" HAVE_LIBUDEV_HEADER)
+    if(HAVE_LIBUDEV_HEADER)
       set(HAVE_LIBUDEV_H TRUE)
       FindLibraryAndSONAME(udev)
       if(UDEV_LIB_SONAME)
         set(SDL_UDEV_DYNAMIC "\"${UDEV_LIB_SONAME}\"")
+        set(HAVE_LIBUDEV TRUE)
+      endif()
+    endif()
+  endif()
+endmacro()
+
+macro(CheckLibUnwind)
+  if(TARGET SDL3_test)
+    set(found_libunwind FALSE)
+    set(_libunwind_src "#include <libunwind.h>\nint main() {unw_context_t context; unw_getcontext(&context); return 0;}")
+
+    if(NOT found_libunwind)
+      cmake_push_check_state()
+      check_c_source_compiles("${_libunwind_src}" LIBC_HAS_WORKING_LIBUNWIND)
+      cmake_pop_check_state()
+      if(LIBC_HAS_WORKING_LIBUNWIND)
+        set(found_libunwind TRUE)
+        target_compile_definitions(SDL3_test PRIVATE HAVE_LIBUNWIND_H)
       endif()
     endif()
+
+    if(NOT found_libunwind)
+      cmake_push_check_state()
+      list(APPEND CMAKE_REQUIRED_LIBRARIES "unwind")
+      check_c_source_compiles("${_libunwind_src}" LIBUNWIND_HAS_WORKINGLIBUNWIND)
+      cmake_pop_check_state()
+      if(LIBUNWIND_HAS_WORKINGLIBUNWIND)
+        set(found_libunwind TRUE)
+        sdl_test_link_dependency(UNWIND LIBS unwind)
+      endif()
+    endif()
+
+    if(NOT found_libunwind)
+      set(LibUnwind_PKG_CONFIG_SPEC libunwind libunwind-generic)
+      pkg_check_modules(PC_LIBUNWIND IMPORTED_TARGET ${LibUnwind_PKG_CONFIG_SPEC})
+      if(PC_LIBUNWIND_FOUND)
+        cmake_push_check_state()
+        list(APPEND CMAKE_REQUIRED_LIBRARIES ${PC_LIBUNWIND_LIBRARIES})
+        list(APPEND CMAKE_REQUIRED_INCLUDES ${PC_LIBUNWIND_INCLUDE_DIRS})
+        check_c_source_compiles("${_libunwind_src}" PC_LIBUNWIND_HAS_WORKING_LIBUNWIND)
+        cmake_pop_check_state()
+        if(PC_LIBUNWIND_HAS_WORKING_LIBUNWIND)
+          set(found_libunwind TRUE)
+          sdl_test_link_dependency(UNWIND LIBS PkgConfig::PC_LIBUNWIND PKG_CONFIG_PREFIX PC_LIBUNWIND PKG_CONFIG_SPECS ${LibUnwind_PKG_CONFIG_SPEC})
+        endif()
+      endif()
+    endif()
+
+    if(found_libunwind)
+      target_compile_definitions(SDL3_test PRIVATE HAVE_LIBUNWIND_H)
+    endif()
   endif()
 endmacro()

+ 128 - 0
cmake/sdlcompilers.cmake

@@ -0,0 +1,128 @@
+macro(SDL_DetectCompiler)
+  set(USE_CLANG FALSE)
+  set(USE_GCC FALSE)
+  set(USE_INTELCC FALSE)
+  set(USE_QCC FALSE)
+  if(CMAKE_C_COMPILER_ID MATCHES "Clang|IntelLLVM")
+    set(USE_CLANG TRUE)
+    # Visual Studio 2019 v16.2 added support for Clang/LLVM.
+    # Check if a Visual Studio project is being generated with the Clang toolset.
+    if(MSVC)
+      set(MSVC_CLANG TRUE)
+    endif()
+  elseif(CMAKE_COMPILER_IS_GNUCC)
+    set(USE_GCC TRUE)
+  elseif(CMAKE_C_COMPILER_ID MATCHES "^Intel$")
+    set(USE_INTELCC TRUE)
+  elseif(CMAKE_C_COMPILER_ID MATCHES "QCC")
+    set(USE_QCC TRUE)
+  endif()
+endmacro()
+
+function(SDL_AddCommonCompilerFlags TARGET)
+  option(SDL_WERROR "Enable -Werror" OFF)
+
+  if(USE_GCC OR USE_CLANG OR USE_INTELCC OR USE_QCC)
+    if(MINGW)
+      # See if GCC's -gdwarf-4 is supported
+      # See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101377 for why this is needed on Windows
+      cmake_push_check_state()
+      check_c_compiler_flag("-gdwarf-4" HAVE_GDWARF_4)
+      if(HAVE_GDWARF_4)
+        target_compile_options(${TARGET} PRIVATE "-gdwarf-4")
+      endif()
+      cmake_pop_check_state()
+    endif()
+
+    # Check for -Wall first, so later things can override pieces of it.
+    # Note: clang-cl treats -Wall as -Weverything (which is very loud),
+    #       /W3 as -Wall, and /W4 as -Wall -Wextra.  So: /W3 is enough.
+    check_c_compiler_flag(-Wall HAVE_GCC_WALL)
+    if(MSVC_CLANG)
+      target_compile_options(${TARGET} PRIVATE "/W3")
+    elseif(HAVE_GCC_WALL)
+      target_compile_options(${TARGET} PRIVATE "-Wall")
+      if(HAIKU)
+        target_compile_options(${TARGET} PRIVATE "-Wno-multichar")
+      endif()
+    endif()
+
+    check_c_compiler_flag(-Wundef HAVE_GCC_WUNDEF)
+    if(HAVE_GCC_WUNDEF)
+      target_compile_options(${TARGET} PRIVATE "-Wundef")
+    endif()
+
+    check_c_compiler_flag(-fno-strict-aliasing HAVE_GCC_NO_STRICT_ALIASING)
+    if(HAVE_GCC_NO_STRICT_ALIASING)
+      target_compile_options(${TARGET} PRIVATE "-fno-strict-aliasing")
+    endif()
+
+    check_c_compiler_flag(-Wdocumentation HAVE_GCC_WDOCUMENTATION)
+    if(HAVE_GCC_WDOCUMENTATION)
+      if(SDL_WERROR)
+        check_c_compiler_flag(-Werror=documentation HAVE_GCC_WERROR_DOCUMENTATION)
+        if(HAVE_GCC_WERROR_DOCUMENTATION)
+          target_compile_options(${TARGET} PRIVATE "-Werror=documentation")
+        endif()
+      endif()
+      target_compile_options(${TARGET} PRIVATE "-Wdocumentation")
+    endif()
+
+    check_c_compiler_flag(-Wdocumentation-unknown-command HAVE_GCC_WDOCUMENTATION_UNKNOWN_COMMAND)
+    if(HAVE_GCC_WDOCUMENTATION_UNKNOWN_COMMAND)
+      if(SDL_WERROR)
+        check_c_compiler_flag(-Werror=documentation-unknown-command HAVE_GCC_WERROR_DOCUMENTATION_UNKNOWN_COMMAND)
+        if(HAVE_GCC_WERROR_DOCUMENTATION_UNKNOWN_COMMAND)
+          target_compile_options(${TARGET} PRIVATE "-Werror=documentation-unknown-command")
+        endif()
+      endif()
+      target_compile_options(${TARGET} PRIVATE "-Wdocumentation-unknown-command")
+    endif()
+
+    check_c_compiler_flag(-fcomment-block-commands=threadsafety HAVE_GCC_COMMENT_BLOCK_COMMANDS)
+    if(HAVE_GCC_COMMENT_BLOCK_COMMANDS)
+      target_compile_options(${TARGET} PRIVATE "-fcomment-block-commands=threadsafety")
+    else()
+      check_c_compiler_flag(/clang:-fcomment-block-commands=threadsafety HAVE_CLANG_COMMENT_BLOCK_COMMANDS)
+      if(HAVE_CLANG_COMMENT_BLOCK_COMMANDS)
+        target_compile_options(${TARGET} PRIVATE "/clang:-fcomment-block-commands=threadsafety")
+      endif()
+    endif()
+
+    check_c_compiler_flag(-Wshadow HAVE_GCC_WSHADOW)
+    if(HAVE_GCC_WSHADOW)
+      target_compile_options(${TARGET} PRIVATE "-Wshadow")
+    endif()
+
+    check_c_compiler_flag(-Wunused-local-typedefs HAVE_GCC_WUNUSED_LOCAL_TYPEDEFS)
+    if(HAVE_GCC_WUNUSED_LOCAL_TYPEDEFS)
+      target_compile_options(${TARGET} PRIVATE "-Wno-unused-local-typedefs")
+    endif()
+  endif()
+
+  if(SDL_WERROR)
+    if(MSVC)
+      check_c_compiler_flag(/WX HAVE_WX)
+      if(HAVE_WX)
+        target_compile_options(${TARGET} PRIVATE "/WX")
+      endif()
+    elseif(USE_GCC OR USE_CLANG OR USE_INTELCC OR USE_QNX)
+      check_c_compiler_flag(-Werror HAVE_WERROR)
+      if(HAVE_WERROR)
+        target_compile_options(${TARGET} PRIVATE "-Werror")
+      endif()
+    endif()
+  endif()
+
+  if(USE_CLANG)
+    check_c_compiler_flag("-fcolor-diagnostics" COMPILER_SUPPORTS_FCOLOR_DIAGNOSTICS)
+    if(COMPILER_SUPPORTS_FCOLOR_DIAGNOSTICS)
+      target_compile_options(${TARGET} PRIVATE "-fcolor-diagnostics")
+    endif()
+  else()
+    check_c_compiler_flag("-fdiagnostics-color=always" COMPILER_SUPPORTS_FDIAGNOSTICS_COLOR_ALWAYS)
+    if(COMPILER_SUPPORTS_FDIAGNOSTICS_COLOR_ALWAYS)
+      target_compile_options(${TARGET} PRIVATE "-fdiagnostics-color=always")
+    endif()
+  endif()
+endfunction()

+ 0 - 8
cmake/sdlfind.cmake

@@ -1,8 +0,0 @@
-macro(sdlFindALSA)
-  find_package(ALSA MODULE)
-  if(ALSA_FOUND AND NOT TARGET ALSA::ALSA)
-    add_Library(ALSA::ALSA UNKNOWN IMPORTED)
-    set_property(TARGET ALSA::ALSA PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${ALSA_INCLUDE_DIRS}")
-    set_property(TARGET ALSA::ALSA APPEND PROPERTY IMPORTED_LOCATION "${ALSA_LIBRARY}")
-  endif()
-endmacro()

+ 2 - 5
cmake/sdlplatform.cmake

@@ -13,10 +13,7 @@ macro(SDL_DetectCMakePlatform)
     elseif(CMAKE_SYSTEM_NAME MATCHES ".*tvOS.*")
       set(SDL_CMAKE_PLATFORM tvOS)
     elseif(CMAKE_SYSTEM_NAME MATCHES ".*iOS.*")
-      # !!! FIXME: remove the version check when we start requiring >= 3.14.0
-      if(CMAKE_VERSION VERSION_LESS 3.14)
-        set(SDL_CMAKE_PLATFORM iOS)
-      endif()
+      set(SDL_CMAKE_PLATFORM iOS)
     endif()
   elseif(CMAKE_SYSTEM_NAME MATCHES "Haiku.*")
     set(SDL_CMAKE_PLATFORM Haiku)
@@ -57,7 +54,7 @@ macro(SDL_DetectCMakePlatform)
   elseif(CMAKE_SYSTEM_NAME MATCHES "QNX.*")
     set(SDL_CMAKE_PLATFORM QNX)
   elseif(CMAKE_SYSTEM_NAME MATCHES "BeOS.*")
-    message_error("BeOS support has been removed as of SDL 2.0.2.")
+    message(FATAL_ERROR "BeOS support has been removed as of SDL 2.0.2.")
   endif()
 
   if(SDL_CMAKE_PLATFORM)

+ 361 - 0
cmake/sdltargets.cmake

@@ -0,0 +1,361 @@
+add_library(SDL3-collector INTERFACE)
+add_library(SDL3_test-collector INTERFACE)
+
+# Use sdl_glob_sources to add glob sources to SDL3-shared, to SDL3-static, or to both.
+function(sdl_glob_sources)
+  cmake_parse_arguments(ARGS "" "" "SHARED;STATIC" ${ARGN})
+  file(GLOB shared_sources ${ARGS_SHARED})
+  file(GLOB static_sources ${ARGS_STATIC})
+  file(GLOB both_sources ${ARGS_UNPARSED_ARGUMENTS})
+  if(TARGET SDL3-shared)
+    target_sources(SDL3-shared PRIVATE ${shared_sources} ${both_sources})
+  endif()
+  if(TARGET SDL3-static)
+    target_sources(SDL3-static PRIVATE ${static_sources} ${both_sources})
+  endif()
+  set_property(TARGET SDL3-collector APPEND PROPERTY INTERFACE_SOURCES ${shared_sources} ${static_sources} ${both_sources})
+endfunction()
+
+# Use sdl_sources to add sources to SDL3-shared, to SDL3-static, or to both.
+function(sdl_sources)
+  cmake_parse_arguments(ARGS "" "" "SHARED;STATIC" ${ARGN})
+  if(TARGET SDL3-shared)
+    target_sources(SDL3-shared PRIVATE ${ARGS_SHARED} ${ARGS_UNPARSED_ARGUMENTS})
+  endif()
+  if(TARGET SDL3-static)
+    target_sources(SDL3-static PRIVATE ${ARGS_STATIC} ${ARGS_UNPARSED_ARGUMENTS})
+  endif()
+  set_property(TARGET SDL3-collector APPEND PROPERTY INTERFACE_SOURCES ${ARGS_SHARED} ${ARGS_STATIC} ${ARGS_UNPARSED_ARGUMENTS})
+endfunction()
+
+# Use sdl_generic_link_dependency to describe a private depency of SDL3. All options are optional.
+# Users should use sdl_link_dependency and sdl_test_link_dependency instead
+# - SHARED_TARGETS: shared targets to add this dependency to
+# - STATIC_TARGETS: static targets to add this dependency to
+# - COLLECTOR: target that stores information, for pc and Config.cmake generation.
+# - INCLUDES: the include directories of the dependency
+# - PKG_CONFIG_PREFIX: name of the prefix, when using the functions of FindPkgConfig
+# - PKG_CONFIG_SPECS: pkg-config spec, used as argument for the functions of FindPkgConfig
+# - PKG_CONFIG_LIBS: libs that will only end up in the Libs.private of sdl3.pc
+# - CMAKE_MODULE: CMake module name of the dependency, used as argument of find_package
+# - LIBS: list of libraries to link to
+# - LINK_OPTIONS: list of link options
+function(sdl_generic_link_dependency ID)
+  cmake_parse_arguments(ARGS "" "COLLECTOR" "SHARED_TARGETS;STATIC_TARGETS;INCLUDES;PKG_CONFIG_LIBS;PKG_CONFIG_PREFIX;PKG_CONFIG_SPECS;CMAKE_MODULE;LIBS;LINK_OPTIONS" ${ARGN})
+  foreach(target IN LISTS ARGS_SHARED_TARGETS)
+    if(TARGET ${target})
+      target_include_directories(${target} SYSTEM PRIVATE ${ARGS_INCLUDES})
+      target_link_libraries(${target} PRIVATE ${ARGS_LIBS})
+      target_link_options(${target} PRIVATE ${ARGS_LINK_OPTIONS})
+    endif()
+  endforeach()
+  foreach(target IN LISTS ARGS_STATIC_TARGETS)
+    if(TARGET ${target})
+      target_include_directories(${target} SYSTEM PRIVATE ${ARGS_INCLUDES})
+      target_link_libraries(${target} PRIVATE ${ARGS_LIBS})
+      target_link_options(${target} INTERFACE ${ARGS_LINK_OPTIONS})
+    endif()
+  endforeach()
+  get_property(ids TARGET ${ARGS_COLLECTOR} PROPERTY INTERFACE_SDL_DEP_IDS)
+  if(NOT ID IN_LIST ids)
+    set_property(TARGET ${ARGS_COLLECTOR} APPEND PROPERTY INTERFACE_SDL_DEP_IDS ${ID})
+  endif()
+  set_property(TARGET ${ARGS_COLLECTOR} APPEND PROPERTY INTERFACE_SDL_DEP_${ID}_PKG_CONFIG_PREFIX ${ARGS_PKG_CONFIG_PREFIX})
+  set_property(TARGET ${ARGS_COLLECTOR} APPEND PROPERTY INTERFACE_SDL_DEP_${ID}_PKG_CONFIG_SPECS ${ARGS_PKG_CONFIG_SPECS})
+  set_property(TARGET ${ARGS_COLLECTOR} APPEND PROPERTY INTERFACE_SDL_DEP_${ID}_PKG_CONFIG_LIBS ${ARGS_PKG_CONFIG_LIBS})
+  set_property(TARGET ${ARGS_COLLECTOR} APPEND PROPERTY INTERFACE_SDL_DEP_${ID}_LIBS ${ARGS_LIBS})
+  set_property(TARGET ${ARGS_COLLECTOR} APPEND PROPERTY INTERFACE_SDL_DEP_${ID}_LINK_OPTIONS ${ARGS_LINK_OPTIONS})
+  set_property(TARGET ${ARGS_COLLECTOR} APPEND PROPERTY INTERFACE_SDL_DEP_${ID}_CMAKE_MODULE ${ARGS_CMAKE_MODULE})
+  set_property(TARGET ${ARGS_COLLECTOR} APPEND PROPERTY INTERFACE_SDL_DEP_${ID}_INCLUDES ${ARGS_INCLUDES})
+endfunction()
+
+function(sdl_link_dependency )
+  sdl_generic_link_dependency(${ARGN} COLLECTOR SDL3-collector SHARED_TARGETS SDL3-shared STATIC_TARGETS SDL3-static)
+endfunction()
+
+function(sdl_test_link_dependency )
+  sdl_generic_link_dependency(${ARGN} COLLECTOR SDL3_test-collector STATIC_TARGETS SDL3_test)
+endfunction()
+
+macro(_get_ARGS_visibility)
+  set(_conflict FALSE)
+  set(visibility)
+  if(ARGS_PRIVATE)
+    set(visibility PRIVATE)
+  elseif(ARGS_PUBLIC)
+    if(visibility)
+      set(_conflict TRUE)
+    endif()
+    set(visibility PUBLIC)
+  elseif(ARGS_INTERFACE)
+    if(visibility)
+      set(_conflict TRUE)
+    endif()
+    set(visibility INTERFACE)
+  endif()
+  if(_conflict OR NOT visibility)
+    message(FATAL_ERROR "PRIVATE/PUBLIC/INTERFACE must be used exactly once")
+  endif()
+  unset(_conflict)
+endmacro()
+
+# Use sdl_link_dependency to add compile definitions to the SDL3 libraries.
+function(sdl_compile_definitions)
+  cmake_parse_arguments(ARGS "PRIVATE;PUBLIC;INTERFACE;NO_EXPORT" "" "" ${ARGN})
+  _get_ARGS_visibility()
+  if(TARGET SDL3-shared)
+    target_compile_definitions(SDL3-shared ${visibility} ${ARGS_UNPARSED_ARGUMENTS})
+  endif()
+  if(TARGET SDL3-static)
+    target_compile_definitions(SDL3-static ${visibility} ${ARGS_UNPARSED_ARGUMENTS})
+  endif()
+  if(NOT ARGS_NO_EXPORT AND (ARGS_PUBLIC OR ARGS_INTERFACE))
+    set_property(TARGET SDL3-collector APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS "${ARGS_UNPARSED_ARGUMENTS}")
+  endif()
+endfunction()
+
+# Use sdl_link_dependency to add compile options to the SDL3 libraries.
+function(sdl_compile_options)
+  cmake_parse_arguments(ARGS "PRIVATE;PUBLIC;INTERFACE;NO_EXPORT" "" "" ${ARGN})
+  _get_ARGS_visibility()
+  set(escaped_opts ${ARGS_UNPARSED_ARGUMENTS})
+  if(ARGS_NO_EXPORT)
+    set(escaped_opts "$<BUILD_INTERFACE:${ARGS_UNPARSED_ARGUMENTS}>")
+  endif()
+  if(TARGET SDL3-shared)
+    target_compile_options(SDL3-shared ${visibility} ${escaped_opts})
+  endif()
+  if(TARGET SDL3-static)
+    target_compile_options(SDL3-static ${visibility} ${escaped_opts})
+  endif()
+  if(NOT ARGS_NO_EXPORT AND (ARGS_PUBLIC OR ARGS_INTERFACE))
+    set_property(TARGET SDL3-collector APPEND PROPERTY INTERFACE_COMPILE_COMPILE_OPTIONS "${ARGS_UNPARSED_ARGUMENTS}")
+  endif()
+endfunction()
+
+# Use sdl_link_dependency to add incude directories to the SDL3 libraries.
+function(sdl_include_directories)
+  cmake_parse_arguments(ARGS "SYSTEM;BEFORE;AFTER;PRIVATE;PUBLIC;INTERFACE;NO_EXPORT" "" "" ${ARGN})
+  set(system "")
+  if(ARGS_SYSTEM)
+    set(system "SYSTEM")
+  endif()
+  set(before_after )
+  if(ARGS_AFTER)
+    set(before_after "AFTER")
+  endif()
+  if(ARGS_BEFORE)
+    if(before_after)
+      message(FATAL_ERROR "before and after are exclusive options")
+    endif()
+    set(before_after "BEFORE")
+  endif()
+  _get_ARGS_visibility()
+  if(TARGET SDL3-shared)
+    target_include_directories(SDL3-shared ${system} ${before_after} ${visibility} ${ARGS_UNPARSED_ARGUMENTS})
+  endif()
+  if(TARGET SDL3-static)
+    target_include_directories(SDL3-static ${system} ${before_after} ${visibility} ${ARGS_UNPARSED_ARGUMENTS})
+  endif()
+  if(NOT NO_EXPORT AND (ARGS_PUBLIC OR ARGS_INTERFACE))
+    set_property(TARGET SDL3-collector APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${ARGS_UNPARSED_ARGUMENTS}")
+  endif()
+endfunction()
+
+# Use sdl_link_dependency to add link directories to the SDL3 libraries.
+function(sdl_link_directories)
+  if(TARGET SDL3-shared)
+    target_link_directories(SDL3-shared PRIVATE ${ARGN})
+  endif()
+  if(TARGET SDL3-static)
+    target_link_directories(SDL3-static INTERFACE ${ARGN})
+  endif()
+endfunction()
+
+# Use sdl_pc_link_options to add a link option, only visible in sdl3.pc
+function(sdl_pc_link_options)
+  set_property(TARGET SDL3-collector APPEND PROPERTY INTERFACE_SDL_PC_LINK_OPTIONS "${ARGN}")
+endfunction()
+
+# Use sdl_pc_link_options to add a link option only to SDL3-shared
+function(sdl_shared_link_options)
+  if(TARGET SDL3-shared)
+    target_link_options(SDL3-shared PRIVATE ${ARGN})
+  endif()
+endfunction()
+
+# Return minimum list of custom SDL CMake modules, used for finding dependencies of SDL.
+function(sdl_cmake_config_required_modules OUTPUT)
+  set(cmake_modules)
+  foreach(collector SDL3-collector SDL3_test-collector)
+    get_property(ids TARGET ${collector} PROPERTY INTERFACE_SDL_DEP_IDS)
+    foreach(ID IN LISTS ids)
+      get_property(CMAKE_MODULE TARGET ${collector} PROPERTY INTERFACE_SDL_DEP_${ID}_CMAKE_MODULE)
+      if(CMAKE_MODULE)
+        if(EXISTS "${SDL3_SOURCE_DIR}/cmake/Find${CMAKE_MODULE}.cmake")
+          list(APPEND cmake_modules "${SDL3_SOURCE_DIR}/cmake/Find${CMAKE_MODULE}.cmake")
+        endif()
+      endif()
+    endforeach()
+    if(cmake_modules)
+      list(APPEND cmake_modules "${SDL3_SOURCE_DIR}/cmake/PkgConfigHelper.cmake")
+    endif()
+  endforeach()
+  set(${OUTPUT} "${cmake_modules}" PARENT_SCOPE)
+endfunction()
+
+# Generate string for SDL3Config.cmake, finding all pkg-config dependencies of SDL3.
+function(sdl_cmake_config_find_pkg_config_commands OUTPUT)
+  cmake_parse_arguments(ARGS "" "COLLECTOR;CONFIG_COMPONENT_FOUND_NAME" "" ${ARGN})
+  if(NOT ARGS_COLLECTOR OR NOT ARGS_CONFIG_COMPONENT_FOUND_NAME)
+    message(FATAL_ERROR "COLLECTOR AND CONFIG_COMPONENT_FOUND_NAME are required arguments")
+  endif()
+  get_property(ids TARGET ${ARGS_COLLECTOR} PROPERTY INTERFACE_SDL_DEP_IDS)
+
+  set(static_pkgconfig_deps_checks)
+  set(static_module_deps_checks)
+  set(cmake_modules_seen)
+
+  foreach(ID IN LISTS ids)
+    get_property(PKG_CONFIG_PREFIX  TARGET ${ARGS_COLLECTOR} PROPERTY INTERFACE_SDL_DEP_${ID}_PKG_CONFIG_PREFIX)
+    get_property(PKG_CONFIG_SPECS   TARGET ${ARGS_COLLECTOR} PROPERTY INTERFACE_SDL_DEP_${ID}_PKG_CONFIG_SPECS)
+    get_property(CMAKE_MODULE       TARGET ${ARGS_COLLECTOR} PROPERTY INTERFACE_SDL_DEP_${ID}_CMAKE_MODULE)
+    if(CMAKE_MODULE AND NOT CMAKE_MODULE IN_LIST cmake_modules_seen)
+      list(APPEND static_module_deps_checks
+        "find_package(${CMAKE_MODULE})"
+        "if(NOT ${CMAKE_MODULE}_FOUND)"
+        "  set(${ARGS_CONFIG_COMPONENT_FOUND_NAME} OFF)"
+        "endif()"
+        )
+      list(APPEND cmake_modules_seen ${CMAKE_MODULE})
+    endif()
+    if(PKG_CONFIG_PREFIX AND PKG_CONFIG_SPECS)
+      string(JOIN " " pkg_config_specs_str ${PKG_CONFIG_SPECS})
+      list(APPEND static_pkgconfig_deps_checks
+        "  pkg_check_modules(${PKG_CONFIG_PREFIX} QUIET IMPORTED_TARGET ${pkg_config_specs_str})"
+        "  if(NOT ${PKG_CONFIG_PREFIX}_FOUND)"
+        "    set(${ARGS_CONFIG_COMPONENT_FOUND_NAME} OFF)"
+        "  endif()"
+      )
+    endif()
+  endforeach()
+
+  set(prefix "  ")
+
+  set(static_module_deps_texts)
+  if(static_module_deps_checks)
+    set(static_module_deps_texts
+      [[set(_original_module_path "${CMAKE_MODULE_PATH}")]]
+      [[list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")]]
+      ${static_module_deps_checks}
+      [[set(CMAKE_MODULE_PATH "${_original_module_path}")]]
+      [[unset(_original_module_path)]]
+    )
+  endif()
+
+  set(static_pkgconfig_deps_texts)
+  if(static_pkgconfig_deps_checks)
+    string(JOIN "\n${prefix}" static_deps_texts_str ${static_deps_texts})
+    list(APPEND static_pkgconfig_deps_texts
+      "find_package(PkgConfig)"
+      "if(PkgConfig_FOUND)"
+      ${static_pkgconfig_deps_checks}
+      "else()"
+      "  set(${ARGS_CONFIG_COMPONENT_FOUND_NAME} OFF)"
+      "endif()"
+  )
+  endif()
+
+  set(text)
+  string(JOIN "\n${prefix}" text ${static_module_deps_texts} ${static_pkgconfig_deps_texts})
+  if(text)
+    set(text "${prefix}${text}")
+  endif()
+
+  set(${OUTPUT} "${text}" PARENT_SCOPE)
+endfunction()
+
+# Create sdl3.pc.
+function(configure_sdl3_pc)
+  # Clean up variables for sdl3.pc
+  if(TARGET SDL3-shared)
+    set(SDL_PC_SECTION_LIBS_PRIVATE "\nLibs.private:")
+  else()
+    set(SDL_PC_SECTION_LIBS_PRIVATE "")
+  endif()
+
+  get_property(ids TARGET SDL3-collector PROPERTY SDL3-collector PROPERTY INTERFACE_SDL_DEP_IDS)
+
+  set(private_requires)
+  set(private_libs)
+  set(private_ldflags)
+
+  foreach(ID IN LISTS ids)
+    get_property(CMAKE_MODULE       TARGET SDL3-collector PROPERTY INTERFACE_SDL_DEP_${ID}_CMAKE_MODULE)
+    get_property(PKG_CONFIG_SPECS   TARGET SDL3-collector PROPERTY INTERFACE_SDL_DEP_${ID}_PKG_CONFIG_SPECS)
+    get_property(PKG_CONFIG_LIBS    TARGET SDL3-collector PROPERTY INTERFACE_SDL_DEP_${ID}_PKG_CONFIG_LIBS)
+    get_property(LIBS               TARGET SDL3-collector PROPERTY INTERFACE_SDL_DEP_${ID}_LIBS)
+    get_property(LINK_OPTIONS       TARGET SDL3-collector PROPERTY INTERFACE_SDL_DEP_${ID}_LINK_OPTIONS)
+
+    list(APPEND private_requires ${PKG_CONFIG_SPECS})
+    list(APPEND private_libs ${PKG_CONFIG_LIBS})
+    if(NOT PKG_CONFIG_SPECS AND NOT CMAKE_MODULE)
+      list(APPEND private_libs ${LIBS})
+      list(APPEND private_ldflags ${LINK_OPTIONS})
+    endif()
+  endforeach()
+
+  list(TRANSFORM private_libs PREPEND "-l")
+  set(SDL_PC_STATIC_LIBS ${private_ldflags} ${private_libs})
+  list(REMOVE_DUPLICATES SDL_PC_STATIC_LIBS)
+  string(JOIN " " SDL_PC_STATIC_LIBS ${SDL_PC_STATIC_LIBS})
+
+  string(JOIN " " SDL_PC_PRIVATE_REQUIRES ${private_requires})
+  string(REGEX REPLACE "(>=|>|=|<|<=)" [[ \1 ]] SDL_PC_PRIVATE_REQUIRES "${SDL_PC_PRIVATE_REQUIRES}")
+
+  get_property(interface_defines TARGET SDL3-collector PROPERTY INTERFACE_COMPILE_DEFINITIONS)
+  list(TRANSFORM interface_defines PREPEND "-D")
+  get_property(interface_includes TARGET SDL3-collector PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
+  list(TRANSFORM interface_includes PREPEND "-I")
+  set(SDL_PC_CFLAGS ${interface_defines} ${interface_includes})
+  string(JOIN " " SDL_PC_CFLAGS ${SDL_PC_CFLAGS})
+
+  get_property(SDL_PC_LIBS TARGET SDL3-collector PROPERTY INTERFACE_SDL_PC_LINK_OPTIONS)
+  string(JOIN " " SDL_PC_LIBS ${SDL_PC_LIBS})
+
+  string(REGEX REPLACE "-lSDL3( |$)" "-l${sdl_static_libname} " SDL_PC_STATIC_LIBS "${SDL_PC_STATIC_LIBS}")
+  if(NOT SDL_SHARED)
+    string(REGEX REPLACE "-lSDL3( |$)" "-l${sdl_static_libname} " SDL_PC_LIBS "${SDL_PC_LIBS}")
+  endif()
+  if(TARGET SDL3-shared AND TARGET SDL3-static AND NOT sdl_static_libname STREQUAL "SDL3")
+    message(STATUS "\"pkg-config --static --libs sdl3\" will return invalid information")
+  endif()
+
+  # Calculate prefix relative to location of sdl3.pc
+  file(RELATIVE_PATH SDL_PATH_PREFIX_RELATIVE_TO_PKGCONFIG "${CMAKE_INSTALL_PREFIX}/${SDL_PKGCONFIG_INSTALLDIR}" "${CMAKE_INSTALL_PREFIX}")
+  string(REGEX REPLACE "[/]+$" "" SDL_PATH_PREFIX_RELATIVE_TO_PKGCONFIG "${SDL_PATH_PREFIX_RELATIVE_TO_PKGCONFIG}")
+  set(SDL_PKGCONFIG_PREFIX "\${pcfiledir}/${SDL_PATH_PREFIX_RELATIVE_TO_PKGCONFIG}")
+
+  configure_file("${SDL3_SOURCE_DIR}/cmake/sdl3.pc.in" "${SDL3_BINARY_DIR}/sdl3.pc" @ONLY)
+endfunction()
+
+# Write list of dependencies to output. Only visible when configuring with --log-level=DEBUG.
+function(debug_show_sdl_deps)
+  get_property(ids TARGET SDL3-collector PROPERTY SDL3-collector PROPERTY INTERFACE_SDL_DEP_IDS)
+
+  foreach(ID IN LISTS ids)
+    message(DEBUG "- id: ${ID}")
+    get_property(INCLUDES           TARGET SDL3-collector PROPERTY INTERFACE_SDL_DEP_${ID}_INCLUDES)
+    get_property(CMAKE_MODULE       TARGET SDL3-collector PROPERTY INTERFACE_SDL_DEP_${ID}_CMAKE_MODULE)
+    get_property(PKG_CONFIG_PREFIX  TARGET SDL3-collector PROPERTY INTERFACE_SDL_DEP_${ID}_PKG_CONFIG_PREFIX)
+    get_property(PKG_CONFIG_SPECS   TARGET SDL3-collector PROPERTY INTERFACE_SDL_DEP_${ID}_PKG_CONFIG_SPECS)
+    get_property(LIBS               TARGET SDL3-collector PROPERTY INTERFACE_SDL_DEP_${ID}_LIBS)
+    get_property(LINK_OPTIONS       TARGET SDL3-collector PROPERTY INTERFACE_SDL_DEP_${ID}_LINK_OPTIONS)
+    message(DEBUG "    INCLUDES: ${INCLUDES}")
+    message(DEBUG "    CMAKE_MODULE: ${CMAKE_MODULE}")
+    message(DEBUG "    PKG_CONFIG_PREFIX: ${PKG_CONFIG_PREFIX}")
+    message(DEBUG "    PKG_CONFIG_SPECS: ${PKG_CONFIG_SPECS}")
+    message(DEBUG "    LIBS: ${LIBS}")
+    message(DEBUG "    LINK_OPTIONS: ${LINK_OPTIONS}")
+  endforeach()
+endfunction()

+ 0 - 2
include/build_config/SDL_build_config.h.cmake

@@ -67,7 +67,6 @@
 #cmakedefine HAVE_SYS_TYPES_H 1
 #cmakedefine HAVE_WCHAR_H 1
 #cmakedefine HAVE_PTHREAD_NP_H 1
-#cmakedefine HAVE_LIBUNWIND_H 1
 
 /* C library functions */
 #cmakedefine HAVE_DLOPEN 1
@@ -195,7 +194,6 @@
 #cmakedefine HAVE_SYSCTLBYNAME 1
 #cmakedefine HAVE_CLOCK_GETTIME 1
 #cmakedefine HAVE_GETPAGESIZE 1
-#cmakedefine HAVE_MPROTECT 1
 #cmakedefine HAVE_ICONV 1
 #cmakedefine HAVE_PTHREAD_SETNAME_NP 1
 #cmakedefine HAVE_PTHREAD_SET_NAME_NP 1

+ 0 - 1
include/build_config/SDL_build_config_emscripten.h

@@ -152,7 +152,6 @@
 #define HAVE_SYSCONF 1
 #define HAVE_CLOCK_GETTIME 1
 /* #undef HAVE_GETPAGESIZE */
-#define HAVE_MPROTECT 1
 #define HAVE_ICONV 1
 
 /* SDL internal assertion support */

+ 0 - 2
include/build_config/SDL_build_config_ios.h

@@ -42,8 +42,6 @@
 #define HAVE_STRING_H 1
 #define HAVE_SYS_TYPES_H 1
 #define HAVE_WCHAR_H 1
-/* The libunwind functions are only available on x86 */
-/* #undef HAVE_LIBUNWIND_H */
 
 /* C library functions */
 #define HAVE_DLOPEN 1

+ 1 - 1
src/video/x11/SDL_x11modes.c

@@ -367,7 +367,7 @@ static SDL_bool CheckXRandR(Display *display, int *major, int *minor)
 #endif
         return SDL_FALSE;
     }
-#endif /* XRANDR_ENABLED_BY_DEFAULT */
+#endif /* XRANDR_DISABLED_BY_DEFAULT */
 
     if (!SDL_X11_HAVE_XRANDR) {
 #ifdef X11MODES_DEBUG

+ 20 - 30
test/CMakeLists.txt

@@ -1,13 +1,12 @@
 #
 # CMake script for building the SDL tests
 #
-
 if(SDL_TESTS_LINK_SHARED)
     set(sdl_name_component SDL3-shared)
 else()
     set(sdl_name_component SDL3-static)
 endif()
-set(HAVE_TESTS_LINK_SHARED "${SDL_TESTS_LINK_SHARED}")
+set(HAVE_TESTS_LINK_SHARED "${SDL_TESTS_LINK_SHARED}" PARENT_SCOPE)
 
 # CMake incorrectly detects opengl32.lib being present on MSVC ARM64
 if(NOT (MSVC AND SDL_CPU_ARM64))
@@ -18,11 +17,10 @@ endif()
 
 set(SDL_TEST_EXECUTABLES)
 
-# FIXME: can be OBJECT library for CMake 3.16
-add_library(sdltests_utils STATIC
+add_library(sdltests_utils OBJECT
     testutils.c
 )
-target_link_libraries(sdltests_utils PRIVATE SDL3::${sdl_name_component})
+target_link_libraries(sdltests_utils PRIVATE SDL3::Headers)
 
 file(GLOB RESOURCE_FILES *.bmp *.wav *.hex moose.dat utf8.txt)
 set(RESOURCE_FILE_NAMES)
@@ -43,6 +41,9 @@ macro(add_sdl_test_executable TARGET)
     if(NOT AST_SOURCES)
         message(FATAL_ERROR "add_sdl_test_executable needs at least one source")
     endif()
+    if(AST_TESTUTILS)
+        list(APPEND AST_SOURCES $<TARGET_OBJECTS:sdltests_utils>)
+    endif()
     if(AST_NEEDS_RESOURCES)
         list(APPEND AST_SOURCES ${RESOURCE_FILES})
     endif()
@@ -51,10 +52,8 @@ macro(add_sdl_test_executable TARGET)
     else()
         add_executable(${TARGET} ${AST_SOURCES})
     endif()
+    SDL_AddCommonCompilerFlags(${TARGET})
     target_link_libraries(${TARGET} PRIVATE SDL3::SDL3_test SDL3::${sdl_name_component})
-    if(AST_TESTUTILS)
-        target_link_libraries(${TARGET} PRIVATE sdltests_utils)
-    endif()
     if(NOT AST_NO_C90 AND NOT SDL_CMAKE_PLATFORM MATCHES "^(n3ds|ps2|psp)$")
         set_property(TARGET ${TARGET} PROPERTY C_STANDARD 90)
         set_property(TARGET ${TARGET} PROPERTY C_EXTENSIONS FALSE)
@@ -86,7 +85,7 @@ macro(add_sdl_test_executable TARGET)
         set_property(TARGET ${TARGET} APPEND PROPERTY ADDITIONAL_CLEAN_FILES "$<TARGET_FILE_DIR:${TARGET}>/$<JOIN:${RESOURCE_FILE_NAMES},$<SEMICOLON>$<TARGET_FILE_DIR:${TARGET}>/>")
     endif()
     if(AST_BUILD_DEPENDENT)
-        target_include_directories(${TARGET} BEFORE PRIVATE $<TARGET_PROPERTY:sdl-build-options,INTERFACE_INCLUDE_DIRECTORIES>)
+        target_include_directories(${TARGET} BEFORE PRIVATE $<TARGET_PROPERTY:SDL3::${sdl_name_component},INCLUDE_DIRECTORIES>)
         target_include_directories(${TARGET} BEFORE PRIVATE ${SDL3_SOURCE_DIR}/src)
     endif()
 
@@ -103,10 +102,7 @@ macro(add_sdl_test_executable TARGET)
         target_compile_definitions(${TARGET} PRIVATE HAVE_OPENGL)
     endif()
 
-    if(TARGET sdl-global-options)
-        target_link_libraries(${TARGET} PRIVATE $<BUILD_INTERFACE:sdl-global-options>)
-    endif()
-
+    # FIXME: only add "${SDL3_BINARY_DIR}/include-config-$<LOWER_CASE:$<CONFIG>>" + include paths of external dependencies
     target_include_directories(${TARGET} PRIVATE "$<TARGET_PROPERTY:SDL3::${sdl_name_component},INCLUDE_DIRECTORIES>")
 endmacro()
 
@@ -189,8 +185,8 @@ set(gamepad_images
     gamepad_touchpad.bmp
 )
 set(gamepad_image_headers)
-find_package(PythonInterp)
-if(PYTHONINTERP_FOUND AND NOT PYTHON_VERSION_STRING VERSION_LESS "3.2")
+find_package(Python3)
+if(Python3_FOUND AND Python3_VERSION VERSION_GREATER_EQUAL "3.2")
     set(xxd "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/xxd.py")
     foreach(bmp ${gamepad_images})
         get_filename_component(bmp_we "${bmp}" NAME_WE)
@@ -199,7 +195,7 @@ if(PYTHONINTERP_FOUND AND NOT PYTHON_VERSION_STRING VERSION_LESS "3.2")
         # Don't add the 'final' headers to the output, to avoid marking them as GENERATED
         # (generated files are removed when running the CLEAN target)
         add_custom_command(OUTPUT "${intermediate}"
-            COMMAND "${PYTHON_EXECUTABLE}" "${xxd}" -i "${CMAKE_CURRENT_SOURCE_DIR}/${bmp}" "-o" "${intermediate}"
+            COMMAND Python3::Interpreter "${xxd}" -i "${CMAKE_CURRENT_SOURCE_DIR}/${bmp}" "-o" "${intermediate}"
             COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${intermediate}" "${final}"
             DEPENDS "${xxd}" "${bmp}"
         )
@@ -273,7 +269,7 @@ endif()
 cmake_push_check_state()
 if(HAVE_WFORMAT)
     # Some compilers ignore -Wformat-extra-args without -Wformat
-    set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Wformat")
+    string(APPEND CMAKE_REQUIRED_FLAGS " -Wformat")
 endif()
 check_c_compiler_flag(-Wformat-extra-args HAVE_WFORMAT_EXTRA_ARGS)
 cmake_pop_check_state()
@@ -390,19 +386,13 @@ endif()
 # Set Apple App ID / Bundle ID.  This is needed to launch apps on some Apple
 # platforms (iOS, for example).
 if(APPLE)
-    if(CMAKE_VERSION VERSION_LESS "3.7.0")
-        # CMake's 'BUILDSYSTEM_TARGETS' property is only available in
-        # CMake 3.7 and above.
-        message(WARNING "Unable to set Bundle ID for Apple .app builds due to old CMake (pre 3.7).")
-    else()
-        foreach(CURRENT_TARGET ${SDL_TEST_EXECUTABLES})
-            set_target_properties("${CURRENT_TARGET}" PROPERTIES
-                MACOSX_BUNDLE_GUI_IDENTIFIER "org.libsdl.${CURRENT_TARGET}"
-                MACOSX_BUNDLE_BUNDLE_VERSION "${SDL3_VERSION}"
-                MACOSX_BUNDLE_SHORT_VERSION_STRING "${SDL3_VERSION}"
-            )
-        endforeach()
-    endif()
+  foreach(CURRENT_TARGET ${SDL_TEST_EXECUTABLES})
+    set_target_properties("${CURRENT_TARGET}" PROPERTIES
+      MACOSX_BUNDLE_GUI_IDENTIFIER "org.libsdl.${CURRENT_TARGET}"
+      MACOSX_BUNDLE_BUNDLE_VERSION "${SDL3_VERSION}"
+      MACOSX_BUNDLE_SHORT_VERSION_STRING "${SDL3_VERSION}"
+    )
+  endforeach()
 endif()
 
 set(TESTS_ENVIRONMENT

部分文件因为文件数量过多而无法显示