SDL: cmake: allow find_package from build directory (requires CMake 3.26)

From ff82341ce933895714a0956805a98d36f3ab6e9b Mon Sep 17 00:00:00 2001
From: Anonymous Maarten <[EMAIL REDACTED]>
Date: Sat, 4 Feb 2023 23:20:03 +0100
Subject: [PATCH] cmake: allow find_package from build directory (requires
 CMake 3.26)

---
 CMakeLists.txt      | 164 +++++++++++++++++++++++++-------------------
 cmake/sdlfind.cmake |   7 +-
 2 files changed, 98 insertions(+), 73 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index afc700330f51..c4ae809dadec 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -78,6 +78,12 @@ if (LIBC_IS_GLIBC AND CMAKE_SIZEOF_VOID_P EQUAL 4)
     target_compile_definitions(sdl-build-options INTERFACE "_FILE_OFFSET_BITS=64")
 endif()
 
+if(CMAKE_VERSION VERSION_LESS "3.26")
+  set(build_local_interface "BUILD_INTERFACE")
+else()
+  set(build_local_interface "BUILD_LOCAL_INTERFACE")
+endif()
+
 # Increment this if there is an incompatible change - but if that happens,
 # we should rename the library from SDL3 to SDL4, at which point this would
 # reset to 0 anyway.
@@ -3231,9 +3237,9 @@ if(SDL_SHARED)
   )
   target_link_libraries(SDL3 PUBLIC $<TARGET_NAME:SDL3::Headers>)
   # This picks up all the compiler options and such we've accumulated up to here.
-  target_link_libraries(SDL3 PRIVATE $<BUILD_INTERFACE:sdl-build-options>)
-  target_link_libraries(SDL3 PRIVATE $<BUILD_INTERFACE:sdl-shared-build-options>)
-  target_link_libraries(SDL3 PRIVATE $<BUILD_INTERFACE:sdl-global-options>)
+  target_link_libraries(SDL3 PRIVATE $<${build_local_interface}:sdl-build-options>)
+  target_link_libraries(SDL3 PRIVATE $<${build_local_interface}:sdl-shared-build-options>)
+  target_link_libraries(SDL3 PRIVATE $<${build_local_interface}:sdl-global-options>)
   if(MINGW OR CYGWIN)
     if(NOT CMAKE_VERSION VERSION_LESS "3.13")
       target_link_options(SDL3 PRIVATE -static-libgcc)
@@ -3275,8 +3281,8 @@ if(SDL_STATIC)
   )
   target_link_libraries(SDL3-static PUBLIC $<TARGET_NAME:SDL3::Headers>)
   # This picks up all the compiler options and such we've accumulated up to here.
-  target_link_libraries(SDL3-static PRIVATE $<BUILD_INTERFACE:sdl-build-options>)
-  target_link_libraries(SDL3-static PRIVATE $<BUILD_INTERFACE:sdl-global-options>)
+  target_link_libraries(SDL3-static PRIVATE $<${build_local_interface}:sdl-build-options>)
+  target_link_libraries(SDL3-static PRIVATE $<${build_local_interface}:sdl-global-options>)
   # Use `Compatible Interface Properties` to allow consumers to enforce a shared/static library
   set_property(TARGET SDL3-static PROPERTY INTERFACE_SDL3_SHARED FALSE)
   set_property(TARGET SDL3-static APPEND PROPERTY COMPATIBLE_INTERFACE_BOOL SDL3_SHARED)
@@ -3297,7 +3303,7 @@ if(SDL_TEST)
   file(GLOB TEST_SOURCES ${SDL3_SOURCE_DIR}/src/test/*.c)
   add_library(SDL3_test STATIC ${TEST_SOURCES})
   add_library(SDL3::SDL3_test ALIAS SDL3_test)
-  target_link_libraries(SDL3_test PRIVATE $<BUILD_INTERFACE:sdl-global-options>)
+  target_link_libraries(SDL3_test PRIVATE $<${build_local_interface}:sdl-global-options>)
   set_target_properties(SDL3_test PROPERTIES
       EXPORT_NAME SDL3_test)
   if(APPLE)
@@ -3320,67 +3326,96 @@ if(SDL_TEST)
   target_link_libraries(SDL3_test PRIVATE ${EXTRA_TEST_LIBS})
 endif()
 
-if(NOT SDL_DISABLE_INSTALL)
+##### Configure installation folders #####
 
-  ##### Configure installation folders #####
+if(WINDOWS AND NOT MINGW)
+  set(SDL_INSTALL_CMAKEDIR_ROOT_DEFAULT "cmake")
+else()
+  set(SDL_INSTALL_CMAKEDIR_ROOT_DEFAULT "${CMAKE_INSTALL_LIBDIR}/cmake")
+endif()
+set(SDL_INSTALL_CMAKEDIR_ROOT "${SDL_INSTALL_CMAKEDIR_ROOT_DEFAULT}" CACHE STRING "Root folder where to install SDL3Config.cmake related files (SDL3 subfolder for MSVC projects)")
 
-  if(WINDOWS AND NOT MINGW)
-    set(SDL_INSTALL_CMAKEDIR_ROOT_DEFAULT "cmake")
-  else()
-    set(SDL_INSTALL_CMAKEDIR_ROOT_DEFAULT "${CMAKE_INSTALL_LIBDIR}/cmake")
-  endif()
-  set(SDL_INSTALL_CMAKEDIR_ROOT "${SDL_INSTALL_CMAKEDIR_ROOT_DEFAULT}" CACHE STRING "Root folder where to install SDL3Config.cmake related files (SDL3 subfolder for MSVC projects)")
+if(FREEBSD)
+  # FreeBSD uses ${PREFIX}/libdata/pkgconfig
+  set(SDL_PKGCONFIG_INSTALLDIR "libdata/pkgconfig")
+else()
+  set(SDL_PKGCONFIG_INSTALLDIR "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
+endif()
 
-  if(FREEBSD)
-    # FreeBSD uses ${PREFIX}/libdata/pkgconfig
-    set(SDL_PKGCONFIG_INSTALLDIR "libdata/pkgconfig")
-  else()
-    set(SDL_PKGCONFIG_INSTALLDIR "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
+if(WINDOWS AND NOT MINGW)
+  set(SDL_INSTALL_CMAKEDIR "${SDL_INSTALL_CMAKEDIR_ROOT}")
+  set(SDL_INSTALL_LICENSEDIR "licenses/SDL3")
+  set(SDL_INSTALL_HEADERSDIR "${CMAKE_INSTALL_INCLUDEDIR}/SDL3")
+elseif(SDL_FRAMEWORK)
+  set(SDL_INSTALL_CMAKEDIR "SDL3.framework/Versions/${SDL_FRAMEWORK_VERSION}/Resources/CMake")
+  set(SDL_INSTALL_LICENSEDIR "Resources")
+  set(SDL_INSTALL_HEADERSDIR "Headers")
+else()
+  set(SDL_INSTALL_CMAKEDIR "${SDL_INSTALL_CMAKEDIR_ROOT}/SDL3")
+  set(SDL_INSTALL_LICENSEDIR "${CMAKE_INSTALL_DATAROOTDIR}/licenses/${PROJECT_NAME}")
+  set(SDL_INSTALL_HEADERSDIR "${CMAKE_INSTALL_INCLUDEDIR}/SDL3")
+endif()
+
+if(SDL_FRAMEWORK)
+  set(SDL_SDL_INSTALL_RESOURCEDIR "SDL3.framework/Resources")
+  set(SDL_SDL_INSTALL_CMAKEDIR "${SDL_SDL_INSTALL_RESOURCEDIR}/CMake")
+  set(SDL_SDL_INSTALL_REAL_RESOURCEDIR "SDL3.framework/Versions/${SDL_FRAMEWORK_VERSION}/Resources")
+  set(SDL_SDL_INSTALL_REAL_CMAKEDIR "${SDL_SDL_INSTALL_REAL_RESOURCEDIR}/CMake")
+
+  # - Install other SDL3*Config.cmake files in SDL3*.framework/Resources/CMake
+  # - The *_RELATIVE_CMAKEDIR variables are the symlinked folders visible from outside
+  set(SDL_SDLstatic_INSTALL_RESOURCEDIR "SDL3-static.framework/Resources")
+  set(SDL_SDLstatic_INSTALL_CMAKEDIR "${SDL_SDLstatic_INSTALL_RESOURCEDIR}/CMake")
+  set(SDL_SDLstatic_INSTALL_CMAKEFILENAME "SDL3-staticConfig.cmake")
+
+  set(SDL_SDLtest_INSTALL_RESOURCEDIR "SDL3_test.framework/Resources")
+  set(SDL_SDLtest_INSTALL_CMAKEDIR "${SDL_SDLtest_INSTALL_RESOURCEDIR}/CMake")
+  set(SDL_SDLtest_INSTALL_CMAKEFILENAME "SDL3_testConfig.cmake")
+else()
+  set(SDL_SDL_INSTALL_RESOURCEDIR ".")
+  set(SDL_SDL_INSTALL_CMAKEDIR ${SDL_INSTALL_CMAKEDIR})
+  set(SDL_SDL_INSTALL_REAL_CMAKEDIR ${SDL_INSTALL_CMAKEDIR})
+
+  # Install SDL3*Targets.cmake files in lib/cmake/SDL3
+  set(SDL_SDLstatic_INSTALL_RESOURCEDIR ".")
+  set(SDL_SDLstatic_INSTALL_CMAKEDIR "${SDL_SDL_INSTALL_CMAKEDIR}")
+  set(SDL_SDLstatic_INSTALL_CMAKEFILENAME "SDL3staticTargets.cmake")
+
+  set(SDL_SDLtest_INSTALL_RESOURCEDIR ".")
+  set(SDL_SDLtest_INSTALL_CMAKEDIR "${SDL_SDL_INSTALL_CMAKEDIR}")
+  set(SDL_SDLtest_INSTALL_CMAKEFILENAME "SDL3testTargets.cmake")
   endif()
 
-  if(WINDOWS AND NOT MINGW)
-    set(SDL_INSTALL_CMAKEDIR "${SDL_INSTALL_CMAKEDIR_ROOT}")
-    set(SDL_INSTALL_LICENSEDIR "licenses/SDL3")
-    set(SDL_INSTALL_HEADERSDIR "${CMAKE_INSTALL_INCLUDEDIR}/SDL3")
-  elseif(SDL_FRAMEWORK)
-    set(SDL_INSTALL_CMAKEDIR "SDL3.framework/Versions/${SDL_FRAMEWORK_VERSION}/Resources/CMake")
-    set(SDL_INSTALL_LICENSEDIR "Resources")
-    set(SDL_INSTALL_HEADERSDIR "Headers")
-  else()
-    set(SDL_INSTALL_CMAKEDIR "${SDL_INSTALL_CMAKEDIR_ROOT}/SDL3")
-    set(SDL_INSTALL_LICENSEDIR "${CMAKE_INSTALL_DATAROOTDIR}/licenses/${PROJECT_NAME}")
-    set(SDL_INSTALL_HEADERSDIR "${CMAKE_INSTALL_INCLUDEDIR}/SDL3")
-  endif()
-
-  if(SDL_FRAMEWORK)
-    set(SDL_SDL_INSTALL_RESOURCEDIR "SDL3.framework/Resources")
-    set(SDL_SDL_INSTALL_CMAKEDIR "${SDL_SDL_INSTALL_RESOURCEDIR}/CMake")
-    set(SDL_SDL_INSTALL_REAL_RESOURCEDIR "SDL3.framework/Versions/${SDL_FRAMEWORK_VERSION}/Resources")
-    set(SDL_SDL_INSTALL_REAL_CMAKEDIR "${SDL_SDL_INSTALL_REAL_RESOURCEDIR}/CMake")
-
-    # - Install other SDL3*Config.cmake files in SDL3*.framework/Resources/CMake
-    # - The *_RELATIVE_CMAKEDIR variables are the symlinked folders visible from outside
-    set(SDL_SDLstatic_INSTALL_RESOURCEDIR "SDL3-static.framework/Resources")
-    set(SDL_SDLstatic_INSTALL_CMAKEDIR "${SDL_SDLstatic_INSTALL_RESOURCEDIR}/CMake")
-    set(SDL_SDLstatic_INSTALL_CMAKEFILENAME "SDL3-staticConfig.cmake")
-
-    set(SDL_SDLtest_INSTALL_RESOURCEDIR "SDL3_test.framework/Resources")
-    set(SDL_SDLtest_INSTALL_CMAKEDIR "${SDL_SDLtest_INSTALL_RESOURCEDIR}/CMake")
-    set(SDL_SDLtest_INSTALL_CMAKEFILENAME "SDL3_testConfig.cmake")
-  else()
-    set(SDL_SDL_INSTALL_RESOURCEDIR ".")
-    set(SDL_SDL_INSTALL_CMAKEDIR ${SDL_INSTALL_CMAKEDIR})
-    set(SDL_SDL_INSTALL_REAL_CMAKEDIR ${SDL_INSTALL_CMAKEDIR})
+if(CMAKE_VERSION VERSION_LESS "3.26")
+  file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/SDL3Targets.cmake" [[message(FATAL_ERROR "find_package(SDL3) using the SDL3 build directory not supported for CMake versions older then 3.26.")]])
+else()
+  export(TARGETS SDL3_Headers NAMESPACE "SDL3::" FILE "SDL3headersTargets.cmake")
+
+  if(SDL_SHARED)
+    export(TARGETS SDL3 NAMESPACE "SDL3::" FILE "SDL3Targets.cmake")
+  endif()
 
-    # Install SDL3*Targets.cmake files in lib/cmake/SDL3
-    set(SDL_SDLstatic_INSTALL_RESOURCEDIR ".")
-    set(SDL_SDLstatic_INSTALL_CMAKEDIR "${SDL_SDL_INSTALL_CMAKEDIR}")
-    set(SDL_SDLstatic_INSTALL_CMAKEFILENAME "SDL3staticTargets.cmake")
+  if(SDL_STATIC)
+    export(TARGETS SDL3-static NAMESPACE "SDL3::" FILE "SDL3staticTargets.cmake")
+  endif()
 
-    set(SDL_SDLtest_INSTALL_RESOURCEDIR ".")
-    set(SDL_SDLtest_INSTALL_CMAKEDIR "${SDL_SDL_INSTALL_CMAKEDIR}")
-    set(SDL_SDLtest_INSTALL_CMAKEFILENAME "SDL3testTargets.cmake")
+  if(SDL_TEST)
+    export(TARGETS SDL3_test NAMESPACE "SDL3::" FILE "SDL3testTargets.cmake")
   endif()
+endif()
+
+configure_file("cmake/sdlfind.cmake" "sdlfind.cmake" COPYONLY)
+
+include(CMakePackageConfigHelpers)
+configure_package_config_file(cmake/SDL3Config.cmake.in SDL3Config.cmake
+  PATH_VARS CMAKE_INSTALL_PREFIX
+  INSTALL_DESTINATION "${SDL_SDL_INSTALL_CMAKEDIR}"
+)
+write_basic_package_version_file("${CMAKE_CURRENT_BINARY_DIR}/SDL3ConfigVersion.cmake"
+  COMPATIBILITY AnyNewerVersion
+)
+
+if(NOT SDL_DISABLE_INSTALL)
 
   ##### sdl3.pc #####
 
@@ -3452,16 +3487,7 @@ if(NOT SDL_DISABLE_INSTALL)
     )
   endif()
 
-  ##### CMake Export files #####
-
-  include(CMakePackageConfigHelpers)
-  configure_package_config_file(cmake/SDL3Config.cmake.in SDL3Config.cmake
-    PATH_VARS CMAKE_INSTALL_PREFIX
-    INSTALL_DESTINATION "${SDL_SDL_INSTALL_CMAKEDIR}"
-  )
-  write_basic_package_version_file("${CMAKE_CURRENT_BINARY_DIR}/SDL3ConfigVersion.cmake"
-    COMPATIBILITY AnyNewerVersion
-  )
+  ##### Install CMake Targets #####
 
   install(EXPORT SDL3headersTargets
     FILE "SDL3headersTargets.cmake"
diff --git a/cmake/sdlfind.cmake b/cmake/sdlfind.cmake
index a8145484f0b8..3f49a57889f8 100644
--- a/cmake/sdlfind.cmake
+++ b/cmake/sdlfind.cmake
@@ -1,9 +1,8 @@
-
 macro(sdlFindALSA)
   find_package(ALSA MODULE)
-  if(ALSA_FOUND AND (NOT TARGET ALSA::ALSA) )
+  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})
+    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()