|
@@ -0,0 +1,288 @@
|
|
|
+#
|
|
|
+# Copyright (c) Contributors to the Open 3D Engine Project.
|
|
|
+# For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
|
|
+#
|
|
|
+# SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
|
+#
|
|
|
+#
|
|
|
+
|
|
|
+if(TARGET 3rdParty::Qt::Core) # Check we are not called multiple times
|
|
|
+ return()
|
|
|
+endif()
|
|
|
+
|
|
|
+set(QT_PACKAGE_NAME qt)
|
|
|
+
|
|
|
+set(QT_PATH "${CMAKE_CURRENT_LIST_DIR}/qt-wayland" CACHE STRING "The root path to Qt" FORCE)
|
|
|
+mark_as_advanced(QT_PATH)
|
|
|
+if(NOT EXISTS ${QT_PATH})
|
|
|
+ message(FATAL_ERROR "Cannot find 3rdParty library ${QT_PACKAGE_NAME} on path ${QT_PATH}")
|
|
|
+endif()
|
|
|
+
|
|
|
+# Force-set QtCore's version here to ensure CMake detects Qt's existence and allows AUTOMOC to work
|
|
|
+set(Qt5Core_VERSION_MAJOR "5" CACHE STRING "Qt's major version" FORCE)
|
|
|
+set(Qt5Core_VERSION_MINOR "15" CACHE STRING "Qt's minor version" FORCE)
|
|
|
+set(Qt5Core_VERSION_PATCH "2" CACHE STRING "Qt's patch version" FORCE)
|
|
|
+mark_as_advanced(Qt5Core_VERSION_MAJOR)
|
|
|
+mark_as_advanced(Qt5Core_VERSION_MINOR)
|
|
|
+mark_as_advanced(Qt5Core_VERSION_PATCH)
|
|
|
+
|
|
|
+set(QT5_COMPONENTS
|
|
|
+ Core
|
|
|
+ Concurrent
|
|
|
+ Gui
|
|
|
+ LinguistTools
|
|
|
+ Network
|
|
|
+ OpenGL
|
|
|
+ Svg
|
|
|
+ Test
|
|
|
+ Widgets
|
|
|
+ Xml
|
|
|
+)
|
|
|
+
|
|
|
+include(${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}/Qt_${PAL_PLATFORM_NAME_LOWERCASE}.cmake)
|
|
|
+
|
|
|
+list(APPEND CMAKE_PREFIX_PATH ${QT_LIB_PATH}/cmake/Qt5)
|
|
|
+
|
|
|
+# Clear the cache for found DIRs
|
|
|
+unset(Qt5_DIR CACHE)
|
|
|
+foreach(component ${QT5_COMPONENTS})
|
|
|
+ unset(Qt5${component}_DIR CACHE)
|
|
|
+endforeach()
|
|
|
+unset(Qt5Positioning_DIR CACHE)
|
|
|
+unset(Qt5PrintSupport_DIR CACHE)
|
|
|
+unset(Qt5Qml_DIR CACHE)
|
|
|
+unset(Qt5QmlModels_DIR CACHE)
|
|
|
+unset(Qt5Quick_DIR CACHE)
|
|
|
+
|
|
|
+# Populate the Qt5 configurations
|
|
|
+find_package(Qt5
|
|
|
+ COMPONENTS ${QT5_COMPONENTS}
|
|
|
+ REQUIRED
|
|
|
+ NO_CMAKE_PACKAGE_REGISTRY
|
|
|
+)
|
|
|
+
|
|
|
+# Now create libraries that wrap the dependency so we can refer to them in our format
|
|
|
+foreach(component ${QT5_COMPONENTS})
|
|
|
+ if(TARGET Qt5::${component})
|
|
|
+
|
|
|
+ # Convert the includes to system includes
|
|
|
+ get_target_property(system_includes Qt5::${component} INTERFACE_INCLUDE_DIRECTORIES)
|
|
|
+ set_target_properties(Qt5::${component} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "") # Clear it in case someone refers to it
|
|
|
+ ly_target_include_system_directories(TARGET Qt5::${component}
|
|
|
+ INTERFACE ${system_includes}
|
|
|
+ )
|
|
|
+
|
|
|
+ # Alias the target with our prefix
|
|
|
+ add_library(3rdParty::Qt::${component} ALIAS Qt5::${component})
|
|
|
+ mark_as_advanced(Qt5${component}_DIR) # Hiding from GUI
|
|
|
+
|
|
|
+ # Qt only has debug and release, we map the configurations we use in o3de. We map all the configurations
|
|
|
+ # except debug to release
|
|
|
+ foreach(conf IN LISTS CMAKE_CONFIGURATION_TYPES)
|
|
|
+ string(TOUPPER ${conf} UCONF)
|
|
|
+ ly_qt_configuration_mapping(${UCONF} MAPPED_CONF)
|
|
|
+ set_target_properties(Qt5::${component} PROPERTIES
|
|
|
+ MAP_IMPORTED_CONFIG_${UCONF} ${MAPPED_CONF}
|
|
|
+ )
|
|
|
+ endforeach()
|
|
|
+
|
|
|
+ endif()
|
|
|
+endforeach()
|
|
|
+
|
|
|
+# Some extra DIR variables we want to hide from GUI
|
|
|
+mark_as_advanced(Qt5_DIR) # Hiding from GUI
|
|
|
+mark_as_advanced(Qt5LinguistTools_DIR) # Hiding from GUI, this variable comes from the LinguistTools module
|
|
|
+mark_as_advanced(Qt5Positioning_DIR)
|
|
|
+mark_as_advanced(Qt5PrintSupport_DIR)
|
|
|
+mark_as_advanced(Qt5Qml_DIR)
|
|
|
+mark_as_advanced(Qt5QmlModels_DIR)
|
|
|
+mark_as_advanced(Qt5Quick_DIR)
|
|
|
+
|
|
|
+# Special case for Qt::Gui, we are using the private headers...
|
|
|
+ly_target_include_system_directories(TARGET Qt5::Gui
|
|
|
+ INTERFACE "${Qt5Gui_PRIVATE_INCLUDE_DIRS}"
|
|
|
+)
|
|
|
+
|
|
|
+# Another special case: Qt:Widgets, we are also using private headers
|
|
|
+ly_target_include_system_directories(TARGET Qt5::Widgets
|
|
|
+ INTERFACE "${Qt5Widgets_PRIVATE_INCLUDE_DIRS}"
|
|
|
+)
|
|
|
+
|
|
|
+# Qt plugins/translations/aux files.
|
|
|
+# We create libraries that wraps them so they get deployed properly.
|
|
|
+# This used to be deployed through winqtdeploy/macqtdeploy, however, those tools
|
|
|
+# are old and unmaintaned, macqtdeploy takes long times to run
|
|
|
+add_library(3rdParty::Qt::Core::Translations INTERFACE IMPORTED GLOBAL)
|
|
|
+file(GLOB tranlation_files ${QT_PATH}/translations/qt_*.qm)
|
|
|
+if(tranlation_files)
|
|
|
+ ly_add_target_files(TARGETS 3rdParty::Qt::Core::Translations
|
|
|
+ FILES ${tranlation_files}
|
|
|
+ OUTPUT_SUBDIRECTORY translations
|
|
|
+ )
|
|
|
+endif()
|
|
|
+ly_add_dependencies(Qt5::Core 3rdParty::Qt::Core::Translations)
|
|
|
+
|
|
|
+# plugins, each platform will define the files it has and the OUTPUT_SUBDIRECTORY
|
|
|
+set(QT_PLUGINS
|
|
|
+ Network
|
|
|
+ Gui
|
|
|
+ Widgets
|
|
|
+)
|
|
|
+foreach(plugin ${QT_PLUGINS})
|
|
|
+ add_library(3rdParty::Qt::${plugin}::Plugins INTERFACE IMPORTED GLOBAL)
|
|
|
+ ly_add_dependencies(Qt5::${plugin} 3rdParty::Qt::${plugin}::Plugins)
|
|
|
+endforeach()
|
|
|
+include(${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}/QtPlugin_${PAL_PLATFORM_NAME_LOWERCASE}.cmake)
|
|
|
+
|
|
|
+# UIC executable
|
|
|
+unset(QT_UIC_EXECUTABLE CACHE)
|
|
|
+find_program(QT_UIC_EXECUTABLE uic HINTS "${QT_PATH}/bin")
|
|
|
+mark_as_advanced(QT_UIC_EXECUTABLE) # Hiding from GUI
|
|
|
+
|
|
|
+# RCC executable
|
|
|
+unset(AUTORCC_EXECUTABLE CACHE)
|
|
|
+find_program(AUTORCC_EXECUTABLE rcc HINTS "${QT_PATH}/bin")
|
|
|
+mark_as_advanced(AUTORCC_EXECUTABLE) # Hiding from GUI
|
|
|
+set(Qt5Core_RCC_EXECUTABLE "${AUTORCC_EXECUTABLE}" CACHE FILEPATH "Qt's resource compiler, used by qt5_add_resources" FORCE)
|
|
|
+mark_as_advanced(Qt5Core_RCC_EXECUTABLE) # Hiding from GUI
|
|
|
+
|
|
|
+# LRELEASE executable
|
|
|
+unset(QT_LRELEASE_EXECUTABLE CACHE)
|
|
|
+find_program(QT_LRELEASE_EXECUTABLE lrelease HINTS "${QT_PATH}/bin")
|
|
|
+mark_as_advanced(QT_LRELEASE_EXECUTABLE) # Hiding from GUI
|
|
|
+if(NOT QT_LRELEASE_EXECUTABLE)
|
|
|
+ message(FATAL_ERROR "Qt's lrelease executbale not found")
|
|
|
+endif()
|
|
|
+set(Qt5_LRELEASE_EXECUTABLE "${QT_LRELEASE_EXECUTABLE}" CACHE FILEPATH "Qt's lrelease executable, used by qt5_add_translation" FORCE)
|
|
|
+mark_as_advanced(Qt5_LRELEASE_EXECUTABLE) # Hiding from GUI
|
|
|
+
|
|
|
+#! ly_qt_uic_target: handles qt's ui files by injecting uic generation
|
|
|
+#
|
|
|
+# AUTOUIC has issues to detect changes in UIC files and trigger regeneration:
|
|
|
+# https://gitlab.kitware.com/cmake/cmake/-/issues/18741
|
|
|
+# So instead, we are going to manually wrap the files. We dont use qt5_wrap_ui because
|
|
|
+# it outputs to ${CMAKE_CURRENT_BINARY_DIR}/ui_${outfile}.h and we want to follow the
|
|
|
+# same folder structure that AUTOUIC uses
|
|
|
+#
|
|
|
+function(ly_qt_uic_target TARGET)
|
|
|
+
|
|
|
+ get_target_property(all_ui_sources ${TARGET} SOURCES)
|
|
|
+ list(FILTER all_ui_sources INCLUDE REGEX "^.*\\.ui$")
|
|
|
+ if(NOT all_ui_sources)
|
|
|
+ message(FATAL_ERROR "Target ${TARGET} contains AUTOUIC but doesnt have any .ui file")
|
|
|
+ endif()
|
|
|
+
|
|
|
+ if(AUTOGEN_BUILD_DIR)
|
|
|
+ set(gen_dir ${AUTOGEN_BUILD_DIR})
|
|
|
+ else()
|
|
|
+ set(gen_dir ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_autogen/include)
|
|
|
+ endif()
|
|
|
+
|
|
|
+ foreach(ui_source ${all_ui_sources})
|
|
|
+
|
|
|
+ get_filename_component(filename ${ui_source} NAME_WE)
|
|
|
+ get_filename_component(dir ${ui_source} DIRECTORY)
|
|
|
+ if(IS_ABSOLUTE ${dir})
|
|
|
+ file(RELATIVE_PATH dir ${CMAKE_CURRENT_SOURCE_DIR} ${dir})
|
|
|
+ endif()
|
|
|
+
|
|
|
+ set(outfolder ${gen_dir}/${dir})
|
|
|
+ set(outfile ${outfolder}/ui_${filename}.h)
|
|
|
+ get_filename_component(infile ${ui_source} ABSOLUTE)
|
|
|
+
|
|
|
+ file(MAKE_DIRECTORY ${outfolder})
|
|
|
+ add_custom_command(OUTPUT ${outfile}
|
|
|
+ COMMAND ${QT_UIC_EXECUTABLE} -o ${outfile} ${infile}
|
|
|
+ MAIN_DEPENDENCY ${infile} VERBATIM
|
|
|
+ COMMENT "UIC ${infile}"
|
|
|
+ )
|
|
|
+
|
|
|
+ set_source_files_properties(${infile} PROPERTIES SKIP_AUTOUIC TRUE)
|
|
|
+ set_source_files_properties(${outfile} PROPERTIES
|
|
|
+ SKIP_AUTOMOC TRUE
|
|
|
+ SKIP_AUTOUIC TRUE
|
|
|
+ GENERATED TRUE
|
|
|
+ )
|
|
|
+ list(APPEND all_ui_wrapped_sources ${outfile})
|
|
|
+
|
|
|
+ endforeach()
|
|
|
+
|
|
|
+ # Add files to the target
|
|
|
+ target_sources(${TARGET} PRIVATE ${all_ui_wrapped_sources})
|
|
|
+ source_group("Generated Files" FILES ${all_ui_wrapped_sources})
|
|
|
+
|
|
|
+ # Add include directories relative to the generated folder
|
|
|
+ # query for the property first to avoid the "NOTFOUND" in a list
|
|
|
+ get_property(has_includes TARGET ${TARGET} PROPERTY INCLUDE_DIRECTORIES SET)
|
|
|
+ if(has_includes)
|
|
|
+ get_property(all_include_directories TARGET ${TARGET} PROPERTY INCLUDE_DIRECTORIES)
|
|
|
+ foreach(dir ${all_include_directories})
|
|
|
+ if(IS_ABSOLUTE ${dir})
|
|
|
+ file(RELATIVE_PATH dir ${CMAKE_CURRENT_SOURCE_DIR} ${dir})
|
|
|
+ endif()
|
|
|
+ list(APPEND new_includes ${gen_dir}/${dir})
|
|
|
+ endforeach()
|
|
|
+ endif()
|
|
|
+ list(APPEND new_includes ${gen_dir})
|
|
|
+ target_include_directories(${TARGET} PRIVATE ${new_includes})
|
|
|
+
|
|
|
+endfunction()
|
|
|
+
|
|
|
+#! ly_add_translations: adds translations (ts) to a target.
|
|
|
+#
|
|
|
+# This wrapper will generate a qrc file with those translations and add the files under "prefix" and add them to
|
|
|
+# the indicated targets. These files will be added under the "Generated Files" filter
|
|
|
+#
|
|
|
+# \arg:TARGETS name of the targets that the translations will be added to
|
|
|
+# \arg:PREFIX prefix where the translation will be located within the qrc file
|
|
|
+# \arg:FILES translation files to add
|
|
|
+#
|
|
|
+function(ly_add_translations)
|
|
|
+
|
|
|
+ set(options)
|
|
|
+ set(oneValueArgs PREFIX)
|
|
|
+ set(multiValueArgs TARGETS FILES)
|
|
|
+
|
|
|
+ cmake_parse_arguments(ly_add_translations "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
|
|
+
|
|
|
+ # Validate input arguments
|
|
|
+ if(NOT ly_add_translations_TARGETS)
|
|
|
+ message(FATAL_ERROR "You must provide at least one target")
|
|
|
+ endif()
|
|
|
+ if(NOT ly_add_translations_FILES)
|
|
|
+ message(FATAL_ERROR "You must provide at least a translation file")
|
|
|
+ endif()
|
|
|
+
|
|
|
+ qt5_add_translation(TRANSLATED_FILES ${ly_add_translations_FILES})
|
|
|
+
|
|
|
+ set(qrc_file_contents
|
|
|
+"<RCC>
|
|
|
+ <qresource prefix=\"/${ly_add_translations_PREFIX}\">
|
|
|
+")
|
|
|
+ foreach(file ${TRANSLATED_FILES})
|
|
|
+ get_filename_component(filename ${file} NAME)
|
|
|
+ string(APPEND qrc_file_contents " <file>${filename}</file>
|
|
|
+")
|
|
|
+ endforeach()
|
|
|
+ string(APPEND qrc_file_contents " </qresource>
|
|
|
+</RCC>
|
|
|
+")
|
|
|
+ set(qrc_file_path ${CMAKE_CURRENT_BINARY_DIR}/i18n_${ly_add_translations_PREFIX}.qrc)
|
|
|
+ file(WRITE
|
|
|
+ ${qrc_file_path}
|
|
|
+ ${qrc_file_contents}
|
|
|
+ )
|
|
|
+ set_source_files_properties(
|
|
|
+ ${TRANSLATED_FILES}
|
|
|
+ ${qrc_file_path}
|
|
|
+ PROPERTIES
|
|
|
+ GENERATED TRUE
|
|
|
+ SKIP_AUTORCC TRUE
|
|
|
+ )
|
|
|
+ qt5_add_resources(RESOURCE_FILE ${qrc_file_path})
|
|
|
+
|
|
|
+ foreach(target ${ly_add_translations_TARGETS})
|
|
|
+ target_sources(${target} PRIVATE "${TRANSLATED_FILES};${qrc_file_path};${RESOURCE_FILE}")
|
|
|
+ endforeach()
|
|
|
+
|
|
|
+endfunction()
|