sdl2-compat: cmake: port over sdlcompilers.cmake from SDL3

From 693364769bdceb0778ac3fec45155965b769bb9f Mon Sep 17 00:00:00 2001
From: Anonymous Maarten <[EMAIL REDACTED]>
Date: Sun, 6 Aug 2023 20:50:07 +0200
Subject: [PATCH] cmake: port over sdlcompilers.cmake from SDL3

---
 CMakeLists.txt           |   5 ++
 cmake/sdlcompilers.cmake | 130 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 135 insertions(+)
 create mode 100644 cmake/sdlcompilers.cmake

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7127acb..97458a2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -82,8 +82,10 @@ include(CMakePushCheckState)
 include(GNUInstallDirs)
 include("${CMAKE_CURRENT_LIST_DIR}/cmake/CheckCPUArchitecture.cmake")
 include("${CMAKE_CURRENT_LIST_DIR}/cmake/sdlchecks.cmake")
+include("${CMAKE_CURRENT_LIST_DIR}/cmake/sdlcompilers.cmake")
 include("${CMAKE_CURRENT_LIST_DIR}/cmake/sdlplatform.cmake")
 
+SDL_DetectCompiler()
 SDL_DetectCMakePlatform()
 CheckOpenGLES()
 
@@ -178,6 +180,7 @@ endif()
 
 add_library(SDL2 SHARED ${SDL2COMPAT_SRCS})
 add_library(SDL2::SDL2 ALIAS SDL2)
+SDL_AddCommonCompilerFlags(SDL2 WERROR "${SDL2COMPAT_WERROR}")
 target_link_libraries(SDL2 PRIVATE $<BUILD_INTERFACE:SDL3::Headers>)
 target_include_directories(SDL2
   INTERFACE
@@ -361,6 +364,7 @@ if(SDL2COMPAT_TESTS)
   function(test_program NAME)
     cmake_parse_arguments(args "NONINTERACTIVE" "TIMEOUT" "SRC" ${ARGN})
     add_executable(${NAME} ${args_SRC})
+    SDL_AddCommonCompilerFlags(${NAME} WERROR "${SDL2COMPAT_WERROR}")
     target_link_libraries(${NAME} PRIVATE SDL2::SDL2main SDL2::SDL2test SDL2::SDL2)
     # Turn off MSVC's aggressive C runtime warnings for the old test programs.
     if(MSVC)
@@ -529,6 +533,7 @@ set(installed_targets SDL2)
 if(SDL2COMPAT_STATICDEVEL AND SDL2COMPAT_DEVEL)
   add_library(SDL2-static STATIC ${SDL2COMPAT_SRCS})
   add_library(SDL2::SDL2-static ALIAS SDL2-static)
+  SDL_AddCommonCompilerFlags(SDL2-static WERROR "${SDL2COMPAT_WERROR}")
   target_link_libraries(SDL2-static PRIVATE $<BUILD_INTERFACE:SDL3::Headers>)
   target_include_directories(SDL2-static
     INTERFACE
diff --git a/cmake/sdlcompilers.cmake b/cmake/sdlcompilers.cmake
new file mode 100644
index 0000000..bbf9b1f
--- /dev/null
+++ b/cmake/sdlcompilers.cmake
@@ -0,0 +1,130 @@
+include(CMakeParseArguments)
+
+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)
+  cmake_parse_arguments(ARGS "" "WERROR" "" ${ARGN})
+
+  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(ARGS_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(ARGS_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(ARGS_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()