FindQt.cmake.wayland 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. #
  2. # Copyright (c) Contributors to the Open 3D Engine Project.
  3. # For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. #
  5. # SPDX-License-Identifier: Apache-2.0 OR MIT
  6. #
  7. #
  8. if(TARGET 3rdParty::Qt::Core) # Check we are not called multiple times
  9. return()
  10. endif()
  11. set(QT_PACKAGE_NAME qt)
  12. set(QT_PATH "${CMAKE_CURRENT_LIST_DIR}/qt-wayland" CACHE STRING "The root path to Qt" FORCE)
  13. mark_as_advanced(QT_PATH)
  14. if(NOT EXISTS ${QT_PATH})
  15. message(FATAL_ERROR "Cannot find 3rdParty library ${QT_PACKAGE_NAME} on path ${QT_PATH}")
  16. endif()
  17. # Force-set QtCore's version here to ensure CMake detects Qt's existence and allows AUTOMOC to work
  18. set(Qt5Core_VERSION_MAJOR "5" CACHE STRING "Qt's major version" FORCE)
  19. set(Qt5Core_VERSION_MINOR "15" CACHE STRING "Qt's minor version" FORCE)
  20. set(Qt5Core_VERSION_PATCH "2" CACHE STRING "Qt's patch version" FORCE)
  21. mark_as_advanced(Qt5Core_VERSION_MAJOR)
  22. mark_as_advanced(Qt5Core_VERSION_MINOR)
  23. mark_as_advanced(Qt5Core_VERSION_PATCH)
  24. set(QT5_COMPONENTS
  25. Core
  26. Concurrent
  27. Gui
  28. LinguistTools
  29. Network
  30. OpenGL
  31. Svg
  32. Test
  33. Widgets
  34. Xml
  35. )
  36. include(${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}/Qt_${PAL_PLATFORM_NAME_LOWERCASE}.cmake)
  37. list(APPEND CMAKE_PREFIX_PATH ${QT_LIB_PATH}/cmake/Qt5)
  38. # Clear the cache for found DIRs
  39. unset(Qt5_DIR CACHE)
  40. foreach(component ${QT5_COMPONENTS})
  41. unset(Qt5${component}_DIR CACHE)
  42. endforeach()
  43. unset(Qt5Positioning_DIR CACHE)
  44. unset(Qt5PrintSupport_DIR CACHE)
  45. unset(Qt5Qml_DIR CACHE)
  46. unset(Qt5QmlModels_DIR CACHE)
  47. unset(Qt5Quick_DIR CACHE)
  48. # Populate the Qt5 configurations
  49. find_package(Qt5
  50. COMPONENTS ${QT5_COMPONENTS}
  51. REQUIRED
  52. NO_CMAKE_PACKAGE_REGISTRY
  53. )
  54. # Now create libraries that wrap the dependency so we can refer to them in our format
  55. foreach(component ${QT5_COMPONENTS})
  56. if(TARGET Qt5::${component})
  57. # Convert the includes to system includes
  58. get_target_property(system_includes Qt5::${component} INTERFACE_INCLUDE_DIRECTORIES)
  59. set_target_properties(Qt5::${component} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "") # Clear it in case someone refers to it
  60. ly_target_include_system_directories(TARGET Qt5::${component}
  61. INTERFACE ${system_includes}
  62. )
  63. # Alias the target with our prefix
  64. add_library(3rdParty::Qt::${component} ALIAS Qt5::${component})
  65. mark_as_advanced(Qt5${component}_DIR) # Hiding from GUI
  66. # Qt only has debug and release, we map the configurations we use in o3de. We map all the configurations
  67. # except debug to release
  68. foreach(conf IN LISTS CMAKE_CONFIGURATION_TYPES)
  69. string(TOUPPER ${conf} UCONF)
  70. ly_qt_configuration_mapping(${UCONF} MAPPED_CONF)
  71. set_target_properties(Qt5::${component} PROPERTIES
  72. MAP_IMPORTED_CONFIG_${UCONF} ${MAPPED_CONF}
  73. )
  74. endforeach()
  75. endif()
  76. endforeach()
  77. # Some extra DIR variables we want to hide from GUI
  78. mark_as_advanced(Qt5_DIR) # Hiding from GUI
  79. mark_as_advanced(Qt5LinguistTools_DIR) # Hiding from GUI, this variable comes from the LinguistTools module
  80. mark_as_advanced(Qt5Positioning_DIR)
  81. mark_as_advanced(Qt5PrintSupport_DIR)
  82. mark_as_advanced(Qt5Qml_DIR)
  83. mark_as_advanced(Qt5QmlModels_DIR)
  84. mark_as_advanced(Qt5Quick_DIR)
  85. # Special case for Qt::Gui, we are using the private headers...
  86. ly_target_include_system_directories(TARGET Qt5::Gui
  87. INTERFACE "${Qt5Gui_PRIVATE_INCLUDE_DIRS}"
  88. )
  89. # Another special case: Qt:Widgets, we are also using private headers
  90. ly_target_include_system_directories(TARGET Qt5::Widgets
  91. INTERFACE "${Qt5Widgets_PRIVATE_INCLUDE_DIRS}"
  92. )
  93. # Qt plugins/translations/aux files.
  94. # We create libraries that wraps them so they get deployed properly.
  95. # This used to be deployed through winqtdeploy/macqtdeploy, however, those tools
  96. # are old and unmaintaned, macqtdeploy takes long times to run
  97. add_library(3rdParty::Qt::Core::Translations INTERFACE IMPORTED GLOBAL)
  98. file(GLOB tranlation_files ${QT_PATH}/translations/qt_*.qm)
  99. if(tranlation_files)
  100. ly_add_target_files(TARGETS 3rdParty::Qt::Core::Translations
  101. FILES ${tranlation_files}
  102. OUTPUT_SUBDIRECTORY translations
  103. )
  104. endif()
  105. ly_add_dependencies(Qt5::Core 3rdParty::Qt::Core::Translations)
  106. # plugins, each platform will define the files it has and the OUTPUT_SUBDIRECTORY
  107. set(QT_PLUGINS
  108. Network
  109. Gui
  110. Widgets
  111. )
  112. foreach(plugin ${QT_PLUGINS})
  113. add_library(3rdParty::Qt::${plugin}::Plugins INTERFACE IMPORTED GLOBAL)
  114. ly_add_dependencies(Qt5::${plugin} 3rdParty::Qt::${plugin}::Plugins)
  115. endforeach()
  116. include(${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}/QtPlugin_${PAL_PLATFORM_NAME_LOWERCASE}.cmake)
  117. # UIC executable
  118. unset(QT_UIC_EXECUTABLE CACHE)
  119. find_program(QT_UIC_EXECUTABLE uic HINTS "${QT_PATH}/bin")
  120. mark_as_advanced(QT_UIC_EXECUTABLE) # Hiding from GUI
  121. # RCC executable
  122. unset(AUTORCC_EXECUTABLE CACHE)
  123. find_program(AUTORCC_EXECUTABLE rcc HINTS "${QT_PATH}/bin")
  124. mark_as_advanced(AUTORCC_EXECUTABLE) # Hiding from GUI
  125. set(Qt5Core_RCC_EXECUTABLE "${AUTORCC_EXECUTABLE}" CACHE FILEPATH "Qt's resource compiler, used by qt5_add_resources" FORCE)
  126. mark_as_advanced(Qt5Core_RCC_EXECUTABLE) # Hiding from GUI
  127. # LRELEASE executable
  128. unset(QT_LRELEASE_EXECUTABLE CACHE)
  129. find_program(QT_LRELEASE_EXECUTABLE lrelease HINTS "${QT_PATH}/bin")
  130. mark_as_advanced(QT_LRELEASE_EXECUTABLE) # Hiding from GUI
  131. if(NOT QT_LRELEASE_EXECUTABLE)
  132. message(FATAL_ERROR "Qt's lrelease executbale not found")
  133. endif()
  134. set(Qt5_LRELEASE_EXECUTABLE "${QT_LRELEASE_EXECUTABLE}" CACHE FILEPATH "Qt's lrelease executable, used by qt5_add_translation" FORCE)
  135. mark_as_advanced(Qt5_LRELEASE_EXECUTABLE) # Hiding from GUI
  136. #! ly_qt_uic_target: handles qt's ui files by injecting uic generation
  137. #
  138. # AUTOUIC has issues to detect changes in UIC files and trigger regeneration:
  139. # https://gitlab.kitware.com/cmake/cmake/-/issues/18741
  140. # So instead, we are going to manually wrap the files. We dont use qt5_wrap_ui because
  141. # it outputs to ${CMAKE_CURRENT_BINARY_DIR}/ui_${outfile}.h and we want to follow the
  142. # same folder structure that AUTOUIC uses
  143. #
  144. function(ly_qt_uic_target TARGET)
  145. get_target_property(all_ui_sources ${TARGET} SOURCES)
  146. list(FILTER all_ui_sources INCLUDE REGEX "^.*\\.ui$")
  147. if(NOT all_ui_sources)
  148. message(FATAL_ERROR "Target ${TARGET} contains AUTOUIC but doesnt have any .ui file")
  149. endif()
  150. if(AUTOGEN_BUILD_DIR)
  151. set(gen_dir ${AUTOGEN_BUILD_DIR})
  152. else()
  153. set(gen_dir ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_autogen/include)
  154. endif()
  155. foreach(ui_source ${all_ui_sources})
  156. get_filename_component(filename ${ui_source} NAME_WE)
  157. get_filename_component(dir ${ui_source} DIRECTORY)
  158. if(IS_ABSOLUTE ${dir})
  159. file(RELATIVE_PATH dir ${CMAKE_CURRENT_SOURCE_DIR} ${dir})
  160. endif()
  161. set(outfolder ${gen_dir}/${dir})
  162. set(outfile ${outfolder}/ui_${filename}.h)
  163. get_filename_component(infile ${ui_source} ABSOLUTE)
  164. file(MAKE_DIRECTORY ${outfolder})
  165. add_custom_command(OUTPUT ${outfile}
  166. COMMAND ${QT_UIC_EXECUTABLE} -o ${outfile} ${infile}
  167. MAIN_DEPENDENCY ${infile} VERBATIM
  168. COMMENT "UIC ${infile}"
  169. )
  170. set_source_files_properties(${infile} PROPERTIES SKIP_AUTOUIC TRUE)
  171. set_source_files_properties(${outfile} PROPERTIES
  172. SKIP_AUTOMOC TRUE
  173. SKIP_AUTOUIC TRUE
  174. GENERATED TRUE
  175. )
  176. list(APPEND all_ui_wrapped_sources ${outfile})
  177. endforeach()
  178. # Add files to the target
  179. target_sources(${TARGET} PRIVATE ${all_ui_wrapped_sources})
  180. source_group("Generated Files" FILES ${all_ui_wrapped_sources})
  181. # Add include directories relative to the generated folder
  182. # query for the property first to avoid the "NOTFOUND" in a list
  183. get_property(has_includes TARGET ${TARGET} PROPERTY INCLUDE_DIRECTORIES SET)
  184. if(has_includes)
  185. get_property(all_include_directories TARGET ${TARGET} PROPERTY INCLUDE_DIRECTORIES)
  186. foreach(dir ${all_include_directories})
  187. if(IS_ABSOLUTE ${dir})
  188. file(RELATIVE_PATH dir ${CMAKE_CURRENT_SOURCE_DIR} ${dir})
  189. endif()
  190. list(APPEND new_includes ${gen_dir}/${dir})
  191. endforeach()
  192. endif()
  193. list(APPEND new_includes ${gen_dir})
  194. target_include_directories(${TARGET} PRIVATE ${new_includes})
  195. endfunction()
  196. #! ly_add_translations: adds translations (ts) to a target.
  197. #
  198. # This wrapper will generate a qrc file with those translations and add the files under "prefix" and add them to
  199. # the indicated targets. These files will be added under the "Generated Files" filter
  200. #
  201. # \arg:TARGETS name of the targets that the translations will be added to
  202. # \arg:PREFIX prefix where the translation will be located within the qrc file
  203. # \arg:FILES translation files to add
  204. #
  205. function(ly_add_translations)
  206. set(options)
  207. set(oneValueArgs PREFIX)
  208. set(multiValueArgs TARGETS FILES)
  209. cmake_parse_arguments(ly_add_translations "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  210. # Validate input arguments
  211. if(NOT ly_add_translations_TARGETS)
  212. message(FATAL_ERROR "You must provide at least one target")
  213. endif()
  214. if(NOT ly_add_translations_FILES)
  215. message(FATAL_ERROR "You must provide at least a translation file")
  216. endif()
  217. qt5_add_translation(TRANSLATED_FILES ${ly_add_translations_FILES})
  218. set(qrc_file_contents
  219. "<RCC>
  220. <qresource prefix=\"/${ly_add_translations_PREFIX}\">
  221. ")
  222. foreach(file ${TRANSLATED_FILES})
  223. get_filename_component(filename ${file} NAME)
  224. string(APPEND qrc_file_contents " <file>${filename}</file>
  225. ")
  226. endforeach()
  227. string(APPEND qrc_file_contents " </qresource>
  228. </RCC>
  229. ")
  230. set(qrc_file_path ${CMAKE_CURRENT_BINARY_DIR}/i18n_${ly_add_translations_PREFIX}.qrc)
  231. file(WRITE
  232. ${qrc_file_path}
  233. ${qrc_file_contents}
  234. )
  235. set_source_files_properties(
  236. ${TRANSLATED_FILES}
  237. ${qrc_file_path}
  238. PROPERTIES
  239. GENERATED TRUE
  240. SKIP_AUTORCC TRUE
  241. )
  242. qt5_add_resources(RESOURCE_FILE ${qrc_file_path})
  243. foreach(target ${ly_add_translations_TARGETS})
  244. target_sources(${target} PRIVATE "${TRANSLATED_FILES};${qrc_file_path};${RESOURCE_FILE}")
  245. endforeach()
  246. endfunction()