DependenciesForBackends.cmake 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. #[[
  2. Set up external dependencies required by the built-in backends.
  3. All dependencies are searched as soft dependencies so that they won't error out if the library is declared by other
  4. means. This file is not meant to be used by consumers of the library, only by the RmlUi CMake project.
  5. ]]
  6. # --- Window/input APIs ---
  7. # SDL 2 and 3 common setup
  8. if(RMLUI_BACKEND MATCHES "^SDL")
  9. set(RMLUI_SDL_VERSION_MAJOR "" CACHE STRING "Major version of SDL to search for, or empty for automatic search.")
  10. mark_as_advanced(RMLUI_SDL_VERSION_MAJOR)
  11. # List of SDL backends that require SDL_image to work with samples
  12. set(RMLUI_SDL_BACKENDS_WITH_SDLIMAGE "SDL_GL2" "SDL_GL3" "SDL_SDLrenderer" "SDL_GPU")
  13. # Determine if the selected SDL backend requires SDL_image
  14. if(RMLUI_BACKEND IN_LIST RMLUI_SDL_BACKENDS_WITH_SDLIMAGE)
  15. set(RMLUI_SDLIMAGE_REQUIRED TRUE)
  16. else()
  17. set(RMLUI_SDLIMAGE_REQUIRED FALSE)
  18. endif()
  19. unset(RMLUI_SDL_BACKENDS_WITH_SDLIMAGE)
  20. endif()
  21. # SDL 3
  22. if(RMLUI_BACKEND MATCHES "^SDL" AND (RMLUI_SDL_VERSION_MAJOR EQUAL "3" OR RMLUI_SDL_VERSION_MAJOR STREQUAL ""))
  23. find_package("SDL3" QUIET)
  24. if(NOT TARGET SDL3::SDL3 AND RMLUI_SDL_VERSION_MAJOR EQUAL "3")
  25. report_dependency_not_found("SDL3" "SDL3" SDL3::SDL3)
  26. endif()
  27. if(TARGET SDL3::SDL3)
  28. #[[
  29. The official target includes the major version number in the target name. However, since we want to link to
  30. SDL independent of its major version, we create a new version-independent target to link against.
  31. ]]
  32. report_dependency_found("SDL3" SDL3::SDL3)
  33. add_library(SDL::SDL INTERFACE IMPORTED)
  34. target_link_libraries(SDL::SDL INTERFACE SDL3::SDL3)
  35. target_compile_definitions(SDL::SDL INTERFACE RMLUI_SDL_VERSION_MAJOR=3)
  36. if(RMLUI_SDLIMAGE_REQUIRED)
  37. find_package("SDL3_image")
  38. report_dependency_found_or_error("SDL3_image" "SDL3_image" SDL3_image::SDL3_image)
  39. add_library(SDL_image::SDL_image INTERFACE IMPORTED)
  40. target_link_libraries(SDL_image::SDL_image INTERFACE SDL3_image::SDL3_image)
  41. endif()
  42. endif()
  43. endif()
  44. # SDL 2
  45. if(RMLUI_BACKEND MATCHES "^SDL" AND NOT TARGET SDL::SDL AND (RMLUI_SDL_VERSION_MAJOR EQUAL "2" OR RMLUI_SDL_VERSION_MAJOR STREQUAL ""))
  46. # Although the official CMake find module is called FindSDL.cmake, the official config module provided by the SDL
  47. # package for its version 2 is called SDL2Config.cmake. Following this trend, the official SDL config files change
  48. # their name according to their major version number
  49. find_package("SDL2")
  50. #[[
  51. Current code operates using a hybrid mode by detecting either the variable or the target due to the possibility
  52. of package managers such as Conan and vcpkg of setting up SDL in their own way but always following the target
  53. naming conventions of the official SDL config files.
  54. ]]
  55. if(NOT TARGET SDL2::SDL2 AND NOT SDL2_FOUND)
  56. report_dependency_not_found("SDL2" "SDL2" SDL2::SDL2)
  57. endif()
  58. # Set up the detected SDL as the SDL2::SDL2 INTERFACE target if it hasn't already been created. This is done for
  59. # consistent referencing across the CMake code regardless of the CMake version used.
  60. if(NOT TARGET SDL2::SDL2)
  61. add_library(SDL2::SDL2 INTERFACE IMPORTED)
  62. set_target_properties(SDL2::SDL2 PROPERTIES
  63. INTERFACE_LINK_LIBRARIES "${SDL2_LIBRARIES}"
  64. INTERFACE_INCLUDE_DIRECTORIES "${SDL2_INCLUDE_DIRS}"
  65. )
  66. endif()
  67. report_dependency_found("SDL2" SDL2::SDL2)
  68. add_library(SDL::SDL INTERFACE IMPORTED)
  69. target_link_libraries(SDL::SDL INTERFACE SDL2::SDL2)
  70. target_compile_definitions(SDL::SDL INTERFACE RMLUI_SDL_VERSION_MAJOR=2)
  71. # Check version requirement for the SDL renderer
  72. if(RMLUI_BACKEND STREQUAL "SDL_SDLrenderer" AND SDL2_VERSION VERSION_LESS "2.0.20")
  73. message(FATAL_ERROR "SDL native renderer backend (${RMLUI_BACKEND}) requires SDL 2.0.20 (found ${SDL2_VERSION}).")
  74. endif()
  75. if(RMLUI_BACKEND STREQUAL "SDL_GPU")
  76. message(FATAL_ERROR "SDL GPU backend (${RMLUI_BACKEND}) requires SDL3 (found ${SDL2_VERSION}).")
  77. endif()
  78. if(RMLUI_SDLIMAGE_REQUIRED)
  79. find_package("SDL2_image")
  80. report_dependency_found_or_error("SDL2_image" "SDL2_image" SDL2_image::SDL2_image)
  81. add_library(SDL_image::SDL_image INTERFACE IMPORTED)
  82. target_link_libraries(SDL_image::SDL_image INTERFACE SDL2_image::SDL2_image)
  83. endif()
  84. endif()
  85. if(RMLUI_BACKEND MATCHES "^SDL" AND NOT TARGET SDL::SDL)
  86. message(FATAL_ERROR "SDL version ${RMLUI_SDL_VERSION_MAJOR} is not supported.")
  87. endif()
  88. # GLFW
  89. if(RMLUI_BACKEND MATCHES "^(BackwardCompatible_)?GLFW")
  90. find_package("glfw3" "3.3")
  91. # Instead of relying on the <package_name>_FOUND variable, we check directly for the target
  92. report_dependency_found_or_error("GLFW" "glfw3" glfw)
  93. endif()
  94. # SFML
  95. if(RMLUI_BACKEND MATCHES "^SFML")
  96. set(RMLUI_SFML_VERSION_MAJOR "" CACHE STRING "Major version of SFML to search for, or empty for automatic search.")
  97. mark_as_advanced(RMLUI_SFML_VERSION_MAJOR)
  98. #[[
  99. Starting with SFML 3.0, the recommended method to find the library is using
  100. the official config file which sets up targets for each module of the library.
  101. The names of the targets follow the namespaced target names convention.
  102. When one of the required modules isn't present as a SFML::<module> target,
  103. that means SFML < 3.0 is being used and we need to set up the target(s) by ourselves.
  104. In SFML 2.5 the first iteration of the SFMLConfig.cmake file was introduced, which
  105. uses a target-oriented approach to exposing the different modules of SFML but it doesn't
  106. use the same names as the config file from SFML 3.0.
  107. ]]
  108. # List of required components in capital case
  109. set(RMLUI_SFML_REQUIRED_COMPONENTS "Graphics" "Window" "System")
  110. # Look for SFML 3 first. We always require the window module, so use that to test if the dependency has been found.
  111. if(NOT TARGET SFML::Window AND (RMLUI_SFML_VERSION_MAJOR EQUAL "3" OR RMLUI_SFML_VERSION_MAJOR STREQUAL ""))
  112. find_package("SFML" "3" COMPONENTS ${RMLUI_SFML_REQUIRED_COMPONENTS} QUIET)
  113. endif()
  114. # Look for SFML 2 next unless another version is found.
  115. if(NOT TARGET SFML::Window AND (RMLUI_SFML_VERSION_MAJOR EQUAL "2" OR RMLUI_SFML_VERSION_MAJOR STREQUAL ""))
  116. list(TRANSFORM RMLUI_SFML_REQUIRED_COMPONENTS TOLOWER OUTPUT_VARIABLE RMLUI_SFML_REQUIRED_COMPONENTS_LOWER_CASE)
  117. find_package("SFML" "2" COMPONENTS ${RMLUI_SFML_REQUIRED_COMPONENTS_LOWER_CASE} QUIET)
  118. endif()
  119. if(NOT TARGET SFML::Window)
  120. #[[
  121. Since the RmlUi CMake project uses the SFML 3.0 namespaced target names, if the version is lower then wrappers
  122. need to be set up.
  123. If e.g. sfml-window exists, then that means the version is either SFML 2.5 or 2.6 which set up
  124. module-specific CMake targets but with different names using a config file. Therefore, we need to alias the
  125. target names to match those declared by SFML 3.0 and used by RmlUi.
  126. ]]
  127. # For each SFML component the project requires
  128. foreach(rmlui_sfml_component ${RMLUI_SFML_REQUIRED_COMPONENTS})
  129. # Make the component name lowercase
  130. string(TOLOWER ${rmlui_sfml_component} rmlui_sfml_component_lower)
  131. if(TARGET sfml-${rmlui_sfml_component_lower})
  132. #[[
  133. RMLUI_CMAKE_MINIMUM_VERSION_RAISE_NOTICE:
  134. Because the target CMake version is 3.10, we can't alias non-global targets nor global imported targets.
  135. Promoting an imported target to the global scope without it being necessary can cause undesired behavior,
  136. specially when the project is consumed as a subdirectory inside another CMake project, therefore is not
  137. recommended. Instead of that, we pseudo-alias the target creating a second INTERFACE target with alias name.
  138. More info: https://cmake.org/cmake/help/latest/command/add_library.html#alias-libraries
  139. ]]
  140. # If the target exists, alias it
  141. add_library(SFML::${rmlui_sfml_component} INTERFACE IMPORTED)
  142. target_link_libraries(SFML::${rmlui_sfml_component} INTERFACE sfml-${rmlui_sfml_component_lower})
  143. endif()
  144. endforeach()
  145. endif()
  146. if(NOT TARGET SFML::Window)
  147. list(TRANSFORM RMLUI_SFML_REQUIRED_COMPONENTS PREPEND "SFML::" OUTPUT_VARIABLE RMLUI_SFML_REQUIRED_TARGETS)
  148. report_dependency_not_found("SFML" "SFML" "${RMLUI_SFML_REQUIRED_TARGETS}")
  149. endif()
  150. report_dependency_found("SFML" SFML)
  151. endif()
  152. # X11
  153. if(RMLUI_BACKEND MATCHES "^X11")
  154. find_package("X11")
  155. endif()
  156. # --- Rendering APIs ---
  157. # OpenGL
  158. # Set preferred OpenGL ABI on Linux for target OpenGL::GL
  159. # More info: https://cmake.org/cmake/help/latest/module/FindOpenGL.html#linux-specific
  160. # RMLUI_CMAKE_MINIMUM_VERSION_RAISE_NOTICE:
  161. # Can remove this with CMake 3.11 as this has become the default. See policy CMP0072.
  162. set(OpenGL_GL_PREFERENCE "GLVND")
  163. if(RMLUI_BACKEND MATCHES "GL2$")
  164. find_package("OpenGL" "2")
  165. report_dependency_found_or_error("OpenGL" "OpenGL" OpenGL::GL)
  166. endif()
  167. # We use 'glad' as an OpenGL loader for GL3 backends, thus we don't normally need to link to OpenGL::GL. The exception
  168. # is for Emscripten, where we use a custom find module to provide OpenGL support.
  169. if(EMSCRIPTEN AND RMLUI_BACKEND MATCHES "GL3$")
  170. find_package("OpenGL" "3")
  171. report_dependency_found_or_error("OpenGL" "OpenGL" OpenGL::GL)
  172. endif()