From 1186beba81e0826e05966ae28aae12a72f290613 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Sun, 26 Apr 2026 22:56:00 -0700
Subject: [PATCH] Added a cmake option USE_VENDORED_SDL, which defaults to ON
This allows Linux distributions to use the system version of SDL
---
CMakeLists.txt | 26 +++++--
cmake/sdlcpu.cmake | 158 ++++++++++++++++++++++++++++++++++++++++
cmake/sdlplatform.cmake | 77 ++++++++++++++++++++
3 files changed, 256 insertions(+), 5 deletions(-)
create mode 100644 cmake/sdlcpu.cmake
create mode 100644 cmake/sdlplatform.cmake
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d7ce918b..0a5a863b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 3.0...4.0)
set(MAJOR_VERSION 4)
set(MINOR_VERSION 0)
set(MICRO_VERSION 0)
+set(SDL_REQUIRED_VERSION 3.4.4)
project(Maelstrom
LANGUAGES C CXX
@@ -25,13 +26,21 @@ if(EMSCRIPTEN)
set(SDL_EMSCRIPTEN_PERSISTENT_PATH /storage)
endif()
-add_subdirectory(maclib)
-
set(PHYSFS_BUILD_SHARED OFF)
set(PHYSFS_BUILD_TEST OFF)
add_subdirectory(external/physfs EXCLUDE_FROM_ALL)
-add_subdirectory(external/SDL EXCLUDE_FROM_ALL)
+option(USE_VENDORED_SDL "Use the vendored version of SDL" TRUE)
+if (USE_VENDORED_SDL)
+ add_subdirectory(external/SDL EXCLUDE_FROM_ALL)
+else()
+ find_package(SDL3 ${SDL_REQUIRED_VERSION} REQUIRED COMPONENTS Headers SDL3-shared)
+ macro(dep_option _NAME _DESC _DEFLT _DEPTEST _FAILDFLT)
+ cmake_dependent_option("${_NAME}" "${_DESC}" "${_DEFLT}" "${_DEPTEST}" "${_FAILDFLT}")
+ endmacro()
+ include("cmake/sdlcpu.cmake")
+ include("cmake/sdlplatform.cmake")
+endif()
# SDL_net's ABI has not yet been finalized
set(original_BUILD_SHARED_LIBS "${BUILD_SHARED_LIBS}")
@@ -39,6 +48,8 @@ set(BUILD_SHARED_LIBS OFF)
add_subdirectory(external/SDL_net SDL_net EXCLUDE_FROM_ALL)
set(BUILD_SHARED_LIBS "${original_BUILD_SHARED_LIBS}")
+add_subdirectory(maclib)
+
SDL_DetectTargetCPUArchitectures(SDL_CPU_NAMES)
SDL_DetectCMakePlatform()
@@ -242,7 +253,10 @@ else()
if(APPLE)
set_property(TARGET ${TARGET_NAME} SDL3-shared PROPERTY INSTALL_RPATH "@executable_path")
else()
- set_property(TARGET ${TARGET_NAME} SDL3-shared PROPERTY INSTALL_RPATH "$ORIGIN")
+ set_property(TARGET ${TARGET_NAME} PROPERTY INSTALL_RPATH "$ORIGIN")
+ if(USE_VENDORED_SDL)
+ set_property(TARGET SDL3-shared PROPERTY INSTALL_RPATH "$ORIGIN")
+ endif( )
endif()
else()
include(GNUInstallDirs)
@@ -255,7 +269,9 @@ else()
)
endif()
- install(TARGETS ${TARGET_NAME} SDL3-shared LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" NAMELINK_SKIP RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
+ if (USE_VENDORED_SDL)
+ install(TARGETS ${TARGET_NAME} SDL3-shared LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" NAMELINK_SKIP RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
+ endif()
if(STEAM)
install(IMPORTED_RUNTIME_ARTIFACTS SteamworksSDK::steam_api)
endif()
diff --git a/cmake/sdlcpu.cmake b/cmake/sdlcpu.cmake
new file mode 100644
index 00000000..a27e7329
--- /dev/null
+++ b/cmake/sdlcpu.cmake
@@ -0,0 +1,158 @@
+function(SDL_DetectTargetCPUArchitectures DETECTED_ARCHS)
+
+ set(known_archs EMSCRIPTEN ARM32 ARM64 ARM64EC LOONGARCH64 POWERPC32 POWERPC64 RISCV32 RISCV64 X86 X64)
+
+ if(APPLE AND CMAKE_OSX_ARCHITECTURES)
+ foreach(known_arch IN LISTS known_archs)
+ set(SDL_CPU_${known_arch} "0" PARENT_SCOPE)
+ endforeach()
+ set(detected_archs)
+ foreach(osx_arch IN LISTS CMAKE_OSX_ARCHITECTURES)
+ if(osx_arch STREQUAL "x86_64")
+ set(SDL_CPU_X64 "1" PARENT_SCOPE)
+ list(APPEND detected_archs "X64")
+ elseif(osx_arch STREQUAL "arm64")
+ set(SDL_CPU_ARM64 "1" PARENT_SCOPE)
+ list(APPEND detected_archs "ARM64")
+ endif()
+ endforeach()
+ set("${DETECTED_ARCHS}" "${detected_archs}" PARENT_SCOPE)
+ return()
+ endif()
+
+ set(detected_archs)
+ foreach(known_arch IN LISTS known_archs)
+ if(SDL_CPU_${known_arch})
+ list(APPEND detected_archs "${known_arch}")
+ endif()
+ endforeach()
+
+ if(detected_archs)
+ set("${DETECTED_ARCHS}" "${detected_archs}" PARENT_SCOPE)
+ return()
+ endif()
+
+ set(arch_check_ARM32 "defined(__arm__) || defined(_M_ARM)")
+ set(arch_check_ARM64 "defined(__aarch64__) || defined(_M_ARM64)")
+ set(arch_check_ARM64EC "defined(_M_ARM64EC)")
+ set(arch_check_EMSCRIPTEN "defined(__EMSCRIPTEN__)")
+ set(arch_check_LOONGARCH64 "defined(__loongarch64)")
+ set(arch_check_POWERPC32 "(defined(__PPC__) || defined(__powerpc__)) && !defined(__powerpc64__)")
+ set(arch_check_POWERPC64 "defined(__PPC64__) || defined(__powerpc64__)")
+ set(arch_check_RISCV32 "defined(__riscv) && defined(__riscv_xlen) && __riscv_xlen == 32")
+ set(arch_check_RISCV64 "defined(__riscv) && defined(__riscv_xlen) && __riscv_xlen == 64")
+ set(arch_check_X86 "defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) ||defined( __i386) || defined(_M_IX86)")
+ set(arch_check_X64 "(defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64)) && !defined(_M_ARM64EC)")
+
+ set(src_vars "")
+ set(src_main "")
+ foreach(known_arch IN LISTS known_archs)
+ set(detected_${known_arch} "0")
+
+ string(APPEND src_vars "
+#if ${arch_check_${known_arch}}
+#define ARCH_${known_arch} \"1\"
+#else
+#define ARCH_${known_arch} \"0\"
+#endif
+const char *arch_${known_arch} = \"INFO<${known_arch}=\" ARCH_${known_arch} \">\";
+")
+ string(APPEND src_main "
+ result += arch_${known_arch}[argc];")
+ endforeach()
+
+ set(src_arch_detect "${src_vars}
+int main(int argc, char *argv[]) {
+ int result = 0;
+ (void)argv;
+${src_main}
+ return result;
+}")
+
+ if(CMAKE_C_COMPILER)
+ set(ext ".c")
+ elseif(CMAKE_CXX_COMPILER)
+ set(ext ".cpp")
+ else()
+ enable_language(C)
+ set(ext ".c")
+ endif()
+ set(path_src_arch_detect "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CMakeTmp/SDL_detect_arch${ext}")
+ file(WRITE "${path_src_arch_detect}" "${src_arch_detect}")
+ set(path_dir_arch_detect "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CMakeTmp/SDL_detect_arch")
+ set(path_bin_arch_detect "${path_dir_arch_detect}/bin")
+
+ set(detected_archs)
+
+ set(msg "Detecting Target CPU Architecture")
+ message(STATUS "${msg}")
+
+ include(CMakePushCheckState)
+
+ set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY")
+
+ cmake_push_check_state(RESET)
+ try_compile(SDL_CPU_CHECK_ALL
+ "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CMakeTmp/SDL_detect_arch"
+ SOURCES "${path_src_arch_detect}"
+ COPY_FILE "${path_bin_arch_detect}"
+ )
+ cmake_pop_check_state()
+ if(NOT SDL_CPU_CHECK_ALL)
+ message(STATUS "${msg} - <ERROR>")
+ message(WARNING "Failed to compile source detecting the target CPU architecture")
+ else()
+ set(re "INFO<([A-Z0-9]+)=([01])>")
+ file(STRINGS "${path_bin_arch_detect}" infos REGEX "${re}")
+
+ foreach(info_arch_01 IN LISTS infos)
+ string(REGEX MATCH "${re}" A "${info_arch_01}")
+ if(NOT "${CMAKE_MATCH_1}" IN_LIST known_archs)
+ message(WARNING "Unknown architecture: \"${CMAKE_MATCH_1}\"")
+ continue()
+ endif()
+ set(arch "${CMAKE_MATCH_1}")
+ set(arch_01 "${CMAKE_MATCH_2}")
+ set(detected_${arch} "${arch_01}")
+ endforeach()
+
+ foreach(known_arch IN LISTS known_archs)
+ if(detected_${known_arch})
+ list(APPEND detected_archs ${known_arch})
+ endif()
+ endforeach()
+ endif()
+
+ if(detected_archs)
+ foreach(known_arch IN LISTS known_archs)
+ set("SDL_CPU_${known_arch}" "${detected_${known_arch}}" CACHE BOOL "Detected architecture ${known_arch}")
+ endforeach()
+ message(STATUS "${msg} - ${detected_archs}")
+ else()
+ include(CheckCSourceCompiles)
+ cmake_push_check_state(RESET)
+ foreach(known_arch IN LISTS known_archs)
+ if(NOT detected_archs)
+ set(cache_variable "SDL_CPU_${known_arch}")
+ set(test_src "
+ int main(int argc, char *argv[]) {
+ #if ${arch_check_${known_arch}}
+ return 0;
+ #else
+ choke
+ #endif
+ }
+ ")
+ check_c_source_compiles("${test_src}" "${cache_variable}")
+ if(${cache_variable})
+ set(SDL_CPU_${known_arch} "1" CACHE BOOL "Detected architecture ${known_arch}")
+ set(detected_archs ${known_arch})
+ else()
+ set(SDL_CPU_${known_arch} "0" CACHE BOOL "Detected architecture ${known_arch}")
+ endif()
+ endif()
+ endforeach()
+ cmake_pop_check_state()
+ endif()
+ set("${DETECTED_ARCHS}" "${detected_archs}" PARENT_SCOPE)
+endfunction()
diff --git a/cmake/sdlplatform.cmake b/cmake/sdlplatform.cmake
new file mode 100644
index 00000000..6c60e0a2
--- /dev/null
+++ b/cmake/sdlplatform.cmake
@@ -0,0 +1,77 @@
+function(SDL_DetectCMakePlatform)
+ set(sdl_cmake_platform )
+ if(WIN32)
+ set(sdl_cmake_platform Windows)
+ elseif(PSP)
+ set(sdl_cmake_platform psp)
+ elseif(APPLE)
+ if(CMAKE_SYSTEM_NAME MATCHES ".*(Darwin|MacOS).*")
+ set(sdl_cmake_platform macOS)
+ elseif(CMAKE_SYSTEM_NAME MATCHES ".*tvOS.*")
+ set(sdl_cmake_platform tvOS)
+ elseif(CMAKE_SYSTEM_NAME MATCHES ".*iOS.*")
+ set(sdl_cmake_platform iOS)
+ elseif(CMAKE_SYSTEM_NAME MATCHES ".*watchOS.*")
+ set(sdl_cmake_platform watchOS)
+ elseif (CMAKE_SYSTEM_NAME MATCHES "visionOS")
+ set(sdl_cmake_platform visionOS)
+ else()
+ message(WARNING "Unknown Apple platform: \"${CMAKE_SYSTEM_NAME}\"")
+ endif()
+ elseif(CMAKE_SYSTEM_NAME MATCHES "Haiku.*")
+ set(sdl_cmake_platform Haiku)
+ elseif(NINTENDO_3DS)
+ set(sdl_cmake_platform n3ds)
+ elseif(CMAKE_SYSTEM_NAME STREQUAL "DOS")
+ set(sdl_cmake_platform dos)
+ elseif(NGAGESDK)
+ set(sdl_cmake_platform ngage)
+ elseif(PS2)
+ set(sdl_cmake_platform ps2)
+ elseif(RISCOS)
+ set(sdl_cmake_platform RISCOS)
+ elseif(VITA)
+ set(sdl_cmake_platform Vita)
+ elseif(CMAKE_SYSTEM_NAME MATCHES ".*Linux")
+ set(sdl_cmake_platform Linux)
+ elseif(CMAKE_SYSTEM_NAME MATCHES "kFreeBSD.*")
+ set(sdl_cmake_platform FreeBSD)
+ elseif(CMAKE_SYSTEM_NAME MATCHES "kNetBSD.*|NetBSD.*")
+ set(sdl_cmake_platform NetBSD)
+ elseif(CMAKE_SYSTEM_NAME MATCHES "kOpenBSD.*|OpenBSD.*")
+ set(sdl_cmake_platform OpenBSD)
+ elseif(CMAKE_SYSTEM_NAME STREQUAL "GNU")
+ # GNU/Hurd must be checked AFTER RISCOS
+ set(sdl_cmake_platform Hurd)
+ elseif(CMAKE_SYSTEM_NAME MATCHES ".*BSDI.*")
+ set(sdl_cmake_platform BSDi)
+ elseif(CMAKE_SYSTEM_NAME MATCHES "DragonFly.*|FreeBSD")
+ set(sdl_cmake_platform FreeBSD)
+ elseif(CMAKE_SYSTEM_NAME MATCHES "SYSV5.*")
+ set(sdl_cmake_platform SYSV5)
+ elseif(CMAKE_SYSTEM_NAME MATCHES "Solaris.*|SunOS.*")
+ set(sdl_cmake_platform Solaris)
+ elseif(CMAKE_SYSTEM_NAME MATCHES "HP-UX.*")
+ set(sdl_cmake_platform HPUX)
+ elseif(CMAKE_SYSTEM_NAME MATCHES "AIX.*")
+ set(sdl_cmake_platform AIX)
+ elseif(CMAKE_SYSTEM_NAME MATCHES "Minix.*")
+ set(sdl_cmake_platform Minix)
+ elseif(CMAKE_SYSTEM_NAME MATCHES "Android.*")
+ set(sdl_cmake_platform Android)
+ elseif(CMAKE_SYSTEM_NAME MATCHES "Emscripten.*")
+ set(sdl_cmake_platform Emscripten)
+ elseif(CMAKE_SYSTEM_NAME MATCHES "QNX.*")
+ set(sdl_cmake_platform QNX)
+ elseif(CMAKE_SYSTEM_NAME MATCHES "BeOS.*")
+ message(FATAL_ERROR "BeOS support has been removed as of SDL 2.0.2.")
+ endif()
+
+ if(sdl_cmake_platform)
+ string(TOUPPER "${sdl_cmake_platform}" _upper_platform)
+ set("${_upper_platform}" TRUE PARENT_SCOPE)
+ else()
+ set(sdl_cmake_platform "unknown")
+ endif()
+ set(SDL_CMAKE_PLATFORM "${sdl_cmake_platform}" PARENT_SCOPE)
+endfunction()