FindSDL.cmake 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. # Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. # file LICENSE.rst or https://cmake.org/licensing for details.
  3. #[=======================================================================[.rst:
  4. FindSDL
  5. -------
  6. Finds the SDL (Simple DirectMedia Layer) library. SDL is a cross-platform
  7. library for developing multimedia software, such as games and emulators.
  8. .. note::
  9. This module is specifically intended for SDL version 1. Starting with version
  10. 2, SDL provides a CMake package configuration file when built with CMake and
  11. should be found using ``find_package(SDL2)``. Similarly, SDL version 3 can be
  12. found using ``find_package(SDL3)``. These newer versions provide separate
  13. :ref:`Imported Targets` that encapsulate usage requirements. Refer to the
  14. official SDL documentation for more information.
  15. Note that the include path for the SDL header has changed in recent SDL 1
  16. versions from ``SDL/SDL.h`` to simply ``SDL.h``. This change aligns with SDL's
  17. convention of using ``#include "SDL.h"`` for portability, as not all systems
  18. install the headers in a ``SDL/`` subdirectory (e.g., FreeBSD).
  19. When targeting macOS and using the SDL framework, be sure to include both
  20. ``SDLmain.h`` and ``SDLmain.m`` in the project. For other platforms, the
  21. ``SDLmain`` library is typically linked using ``-lSDLmain``, which this module
  22. will attempt to locate automatically. Additionally, for macOS, this module will
  23. add the ``-framework Cocoa`` flag as needed.
  24. Imported Targets
  25. ^^^^^^^^^^^^^^^^
  26. This module provides the following :ref:`Imported Targets`:
  27. ``SDL::SDL``
  28. .. versionadded:: 3.19
  29. Target encapsulating the SDL library usage requirements, available if SDL is
  30. found.
  31. Result Variables
  32. ^^^^^^^^^^^^^^^^
  33. This module defines the following variables:
  34. ``SDL_FOUND``
  35. Boolean indicating whether the (requested version of) SDL is found.
  36. ``SDL_VERSION``
  37. .. versionadded:: 3.19
  38. The human-readable string containing the version of SDL found.
  39. ``SDL_VERSION_MAJOR``
  40. .. versionadded:: 3.19
  41. The major version of SDL found.
  42. ``SDL_VERSION_MINOR``
  43. .. versionadded:: 3.19
  44. The minor version of SDL found.
  45. ``SDL_VERSION_PATCH``
  46. .. versionadded:: 3.19
  47. The patch version of SDL found.
  48. ``SDL_INCLUDE_DIRS``
  49. .. versionadded:: 3.19
  50. Include directories needed to use SDL.
  51. ``SDL_LIBRARIES``
  52. .. versionadded:: 3.19
  53. Libraries needed to link against to use SDL.
  54. Cache Variables
  55. ^^^^^^^^^^^^^^^
  56. These variables may optionally be set to help this module find the correct
  57. files:
  58. ``SDL_INCLUDE_DIR``
  59. The directory containing the ``SDL.h`` header file.
  60. ``SDL_LIBRARY``
  61. A list of libraries containing the path to the SDL library and libraries
  62. needed to link against to use SDL.
  63. Hints
  64. ^^^^^
  65. This module accepts the following variables:
  66. ``SDL_BUILDING_LIBRARY``
  67. When set to boolean true, the ``SDL_main`` library will be excluded from
  68. linking, as it is not required when building the SDL library itself (only
  69. applications need ``main()`` function). If not set, this module assumes an
  70. application is being built and attempts to locate and include the appropriate
  71. ``SDL_main`` link flags in the returned ``SDL_LIBRARY`` variable.
  72. ``SDLDIR``
  73. Environment variable that can be set to help locate an SDL library installed
  74. in a custom location. It should point to the installation destination that
  75. was used when configuring, building, and installing SDL library:
  76. ``./configure --prefix=$SDLDIR``.
  77. On macOS, setting this variable will prefer the Framework version (if found)
  78. over others. In this case, the cache value of ``SDL_LIBRARY`` would need to
  79. be manually changed to override this selection or set the
  80. :variable:`CMAKE_INCLUDE_PATH` variable to modify the search paths.
  81. Troubleshooting
  82. ^^^^^^^^^^^^^^^
  83. In case the SDL library is not found automatically, the ``SDL_LIBRARY_TEMP``
  84. variable may be empty, and ``SDL_LIBRARY`` will not be set. This typically
  85. means that CMake could not locate the SDL library (e.g., ``SDL.dll``,
  86. ``libSDL.so``, ``SDL.framework``, etc.). To resolve this, manually set
  87. ``SDL_LIBRARY_TEMP`` to the correct path and reconfigure the project.
  88. Similarly, if ``SDLMAIN_LIBRARY`` is unset, it may also need to be specified
  89. manually. These variables are used to construct the final ``SDL_LIBRARY``
  90. value. If they are not set, ``SDL_LIBRARY`` will remain undefined.
  91. Deprecated Variables
  92. ^^^^^^^^^^^^^^^^^^^^
  93. These variables are obsolete and provided for backwards compatibility:
  94. ``SDL_VERSION_STRING``
  95. .. deprecated:: 3.19
  96. Superseded by the ``SDL_VERSION`` with the same value.
  97. The human-readable string containing the version of SDL if found.
  98. Examples
  99. ^^^^^^^^
  100. Finding SDL library and linking it to a project target:
  101. .. code-block:: cmake
  102. find_package(SDL)
  103. target_link_libraries(project_target PRIVATE SDL::SDL)
  104. When working with SDL version 2, the upstream package provides the
  105. ``SDL2::SDL2`` imported target directly. It can be used in a project without
  106. using this module:
  107. .. code-block:: cmake
  108. find_package(SDL2)
  109. target_link_libraries(project_target PRIVATE SDL2::SDL2)
  110. Similarly, for SDL version 3:
  111. .. code-block:: cmake
  112. find_package(SDL3)
  113. target_link_libraries(project_target PRIVATE SDL3::SDL3)
  114. See Also
  115. ^^^^^^^^
  116. * The :module:`FindSDL_gfx` module to find the SDL_gfx library.
  117. * The :module:`FindSDL_image` module to find the SDL_image library.
  118. * The :module:`FindSDL_mixer` module to find the SDL_mixer library.
  119. * The :module:`FindSDL_net` module to find the SDL_net library.
  120. * The :module:`FindSDL_sound` module to find the SDL_sound library.
  121. * The :module:`FindSDL_ttf` module to find the SDL_ttf library.
  122. #]=======================================================================]
  123. cmake_policy(PUSH)
  124. cmake_policy(SET CMP0159 NEW) # file(STRINGS) with REGEX updates CMAKE_MATCH_<n>
  125. find_path(SDL_INCLUDE_DIR SDL.h
  126. HINTS
  127. ENV SDLDIR
  128. PATH_SUFFIXES SDL SDL12 SDL11
  129. # path suffixes to search inside ENV{SDLDIR}
  130. include/SDL include/SDL12 include/SDL11 include
  131. )
  132. if(CMAKE_SIZEOF_VOID_P EQUAL 8)
  133. set(VC_LIB_PATH_SUFFIX lib/x64)
  134. else()
  135. set(VC_LIB_PATH_SUFFIX lib/x86)
  136. endif()
  137. # SDL-1.1 is the name used by FreeBSD ports...
  138. # don't confuse it for the version number.
  139. find_library(SDL_LIBRARY_TEMP
  140. NAMES SDL SDL-1.1
  141. HINTS
  142. ENV SDLDIR
  143. PATH_SUFFIXES lib ${VC_LIB_PATH_SUFFIX}
  144. )
  145. # Hide this cache variable from the user, it's an internal implementation
  146. # detail. The documented library variable for the user is SDL_LIBRARY
  147. # which is derived from SDL_LIBRARY_TEMP further below.
  148. set_property(CACHE SDL_LIBRARY_TEMP PROPERTY TYPE INTERNAL)
  149. if(NOT SDL_BUILDING_LIBRARY)
  150. if(NOT SDL_INCLUDE_DIR MATCHES ".framework")
  151. # Non-OS X framework versions expect you to also dynamically link to
  152. # SDLmain. This is mainly for Windows and OS X. Other (Unix) platforms
  153. # seem to provide SDLmain for compatibility even though they don't
  154. # necessarily need it.
  155. find_library(SDLMAIN_LIBRARY
  156. NAMES SDLmain SDLmain-1.1
  157. HINTS
  158. ENV SDLDIR
  159. PATH_SUFFIXES lib ${VC_LIB_PATH_SUFFIX}
  160. PATHS
  161. /opt
  162. )
  163. endif()
  164. endif()
  165. # SDL may require threads on your system.
  166. # The Apple build may not need an explicit flag because one of the
  167. # frameworks may already provide it.
  168. # But for non-OSX systems, I will use the CMake Threads package.
  169. if(NOT APPLE)
  170. find_package(Threads)
  171. endif()
  172. # MinGW needs an additional link flag, -mwindows
  173. # It's total link flags should look like -lmingw32 -lSDLmain -lSDL -mwindows
  174. if(MINGW)
  175. set(MINGW32_LIBRARY mingw32 "-mwindows" CACHE STRING "link flags for MinGW")
  176. endif()
  177. if(SDL_LIBRARY_TEMP)
  178. # For SDLmain
  179. if(SDLMAIN_LIBRARY AND NOT SDL_BUILDING_LIBRARY)
  180. list(FIND SDL_LIBRARY_TEMP "${SDLMAIN_LIBRARY}" _SDL_MAIN_INDEX)
  181. if(_SDL_MAIN_INDEX EQUAL -1)
  182. set(SDL_LIBRARY_TEMP "${SDLMAIN_LIBRARY}" ${SDL_LIBRARY_TEMP})
  183. endif()
  184. unset(_SDL_MAIN_INDEX)
  185. endif()
  186. # For OS X, SDL uses Cocoa as a backend so it must link to Cocoa.
  187. # CMake doesn't display the -framework Cocoa string in the UI even
  188. # though it actually is there if I modify a preused variable.
  189. # I think it has something to do with the CACHE STRING.
  190. # So I use a temporary variable until the end so I can set the
  191. # "real" variable in one-shot.
  192. if(APPLE)
  193. set(SDL_LIBRARY_TEMP ${SDL_LIBRARY_TEMP} "-framework Cocoa")
  194. endif()
  195. # For threads, as mentioned Apple doesn't need this.
  196. # In fact, there seems to be a problem if I used the Threads package
  197. # and try using this line, so I'm just skipping it entirely for OS X.
  198. if(NOT APPLE)
  199. set(SDL_LIBRARY_TEMP ${SDL_LIBRARY_TEMP} ${CMAKE_THREAD_LIBS_INIT})
  200. endif()
  201. # For MinGW library
  202. if(MINGW)
  203. set(SDL_LIBRARY_TEMP ${MINGW32_LIBRARY} ${SDL_LIBRARY_TEMP})
  204. endif()
  205. # Set the final string here so the GUI reflects the final state.
  206. set(SDL_LIBRARY ${SDL_LIBRARY_TEMP} CACHE STRING "Where the SDL Library can be found")
  207. endif()
  208. if(SDL_INCLUDE_DIR AND EXISTS "${SDL_INCLUDE_DIR}/SDL_version.h")
  209. file(STRINGS "${SDL_INCLUDE_DIR}/SDL_version.h" SDL_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL_MAJOR_VERSION[ \t]+[0-9]+$")
  210. file(STRINGS "${SDL_INCLUDE_DIR}/SDL_version.h" SDL_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL_MINOR_VERSION[ \t]+[0-9]+$")
  211. file(STRINGS "${SDL_INCLUDE_DIR}/SDL_version.h" SDL_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL_PATCHLEVEL[ \t]+[0-9]+$")
  212. string(REGEX REPLACE "^#define[ \t]+SDL_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL_VERSION_MAJOR "${SDL_VERSION_MAJOR_LINE}")
  213. string(REGEX REPLACE "^#define[ \t]+SDL_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL_VERSION_MINOR "${SDL_VERSION_MINOR_LINE}")
  214. string(REGEX REPLACE "^#define[ \t]+SDL_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL_VERSION_PATCH "${SDL_VERSION_PATCH_LINE}")
  215. unset(SDL_VERSION_MAJOR_LINE)
  216. unset(SDL_VERSION_MINOR_LINE)
  217. unset(SDL_VERSION_PATCH_LINE)
  218. set(SDL_VERSION ${SDL_VERSION_MAJOR}.${SDL_VERSION_MINOR}.${SDL_VERSION_PATCH})
  219. set(SDL_VERSION_STRING ${SDL_VERSION})
  220. endif()
  221. include(FindPackageHandleStandardArgs)
  222. find_package_handle_standard_args(SDL
  223. REQUIRED_VARS SDL_LIBRARY SDL_INCLUDE_DIR
  224. VERSION_VAR SDL_VERSION_STRING)
  225. if(SDL_FOUND)
  226. set(SDL_LIBRARIES ${SDL_LIBRARY})
  227. set(SDL_INCLUDE_DIRS ${SDL_INCLUDE_DIR})
  228. if(NOT TARGET SDL::SDL)
  229. add_library(SDL::SDL INTERFACE IMPORTED)
  230. set_target_properties(SDL::SDL PROPERTIES
  231. INTERFACE_INCLUDE_DIRECTORIES "${SDL_INCLUDE_DIR}"
  232. INTERFACE_LINK_LIBRARIES "${SDL_LIBRARY}")
  233. endif()
  234. endif()
  235. cmake_policy(POP)