Ver Fonte

Qt Package fix for Mac (#113)

* Fix issue with mac qt package where the qt includes of modules are not in the main include folder of the package
* Made mac-specific FindQt.cmake to include back the inclusion of QT_PATH/include in the systems include folder
* Fix minor python error in copy_platform_cmakes.py

Signed-off-by: spham <[email protected]>
Steve Pham há 3 anos atrás
pai
commit
95a16e46bf

+ 290 - 0
package-system/Qt/FindQt.cmake.mac

@@ -0,0 +1,290 @@
+#
+# 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" 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}
+                ${QT_PATH}/include
+        )
+
+        # 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()

+ 15 - 0
package-system/Qt/build-darwin.sh

@@ -87,4 +87,19 @@ for qtlib in "${qtarray[@]}"; do
     make module-$qtlib-install_subtargets
     echo $qtlib installed.
 done
+
+# The installation target on darwin is not installing the framework's header paths in the main
+# include folder. Create a symlink to the headers there for backwards compatibility
+cd $TARGET_INSTALL_ROOT/include
+
+qtframeworks=(QtConcurrent QtCore QtDBus QtDesigner QtDesignerComponents QtGui QtHelp QtMacExtras QtNetwork QtOpenGL QtPrintSupport QtQml QtQmlModels QtQmlWorkerScript QtQuick QtQuickParticles QtQuickShapes QtQuickTest QtQuickWidgets QtSql QtSvg QtTest QtUiPlugin QtWidgets QtXml QtZlib)
+for qtframework in "${qtframeworks[@]}"; do
+    if [ -d $TARGET_INSTALL_ROOT/lib/$qtframework.framework/Headers ]; then
+        echo "Linking ${TARGET_INSTALL_ROOT}/lib/${qtframework}.framework/Headers/ to ${TARGET_INSTALL_ROOT}/include/${qtframework}"
+        ln -s ../lib/$qtframework.framework/Headers/ $qtframework
+    else
+        echo "Unable to find $TARGET_INSTALL_ROOT/lib/${qtframework}.framework/Headers (${qtframework}) Skipping.."
+    fi
+done
+
 echo Qt installed successfully!

+ 3 - 1
package-system/Qt/build_config.json

@@ -3,7 +3,6 @@
     "git_tag": "5.15.1-o3de",
     "git_commit": "b3a1a6947422928e8aecb14ad607199e9720d266",
     "package_name": "qt",
-    "package_version": "5.15.2-rev7",
     "package_url": "https://www.qt.io/",
     "package_license": "LGPL-3.0",
     "package_license_file": "qt/LICENSE.LGPLv3",
@@ -12,6 +11,7 @@
     "Platforms": {
         "Windows": {
             "Windows": {
+                "package_version": "5.15.2-rev7",
                 "patch_file": "qt-image-format-windows.patch",
                 "depends_on_packages": [
                     ["OpenSSL-1.1.1m-rev1-windows", "7d8d3904c70b7da471f777ee788678614a9b20d3ac926b7c0d60ccf2a17c7959", ""],
@@ -29,6 +29,8 @@
         },
         "Darwin": {
             "Mac": {
+                "cmake_find_source": "FindQt.cmake.mac",
+                "package_version": "5.15.2-rev8",
                 "patch_file": "qt-image-format.patch",
                 "depends_on_packages": [
                     ["tiff-4.2.0.15-rev3-mac", "c2615ccdadcc0e1d6c5ed61e5965c4d3a82193d206591b79b805c3b3ff35a4bf", ""],

+ 1 - 1
package-system/Qt/copy_platform_cmakes.py

@@ -45,7 +45,7 @@ additional_copyright_notices = ["QT-NOTICE.TXT",
                                 os.path.join("temp","src", "qtfeedback", "LGPL_EXCEPTION.txt")]
 for file in additional_copyright_notices:
     if not os.path.isfile(file):
-        printf(f"Error: Cannot locate copyright notice file: {file}")
+        print(f"Error: Cannot locate copyright notice file: {file}")
         sys.exit(1)
     print(f"Copying {file} => {package_qt_root}")
     shutil.copy2(file, package_qt_root)

+ 2 - 2
package_build_list_host_darwin.json

@@ -41,7 +41,7 @@
         "mcpp-2.7.2_az.2-rev1-mac": "package-system/mcpp/get_and_build_mcpp.py mcpp-2.7.2_az.2-rev1",
         "mikkelsen-1.0.0.4-mac": "package-system/mikkelsen/build_package_image.py --platform mac",
         "mikkelsen-1.0.0.4-ios": "package-system/mikkelsen/build_package_image.py --platform ios",
-        "qt-5.15.2-rev7-mac": "Scripts/extras/pull_and_build_from_git.py ../../package-system/Qt --platform-name Mac --package-root ../../package-system/Qt/temp --clean",
+        "qt-5.15.2-rev8-mac": "Scripts/extras/pull_and_build_from_git.py ../../package-system/Qt --platform-name Mac --package-root ../../package-system/Qt/temp --clean",
         "zlib-1.2.11-rev5-mac": "Scripts/extras/pull_and_build_from_git.py ../../package-system/zlib --platform-name Mac --package-root ../../package-system --clean",
         "zlib-1.2.11-rev5-ios": "Scripts/extras/pull_and_build_from_git.py ../../package-system/zlib --platform-name iOS --package-root ../../package-system --clean",
         "lz4-1.9.3-vcpkg-rev4-mac": "package-system/lz4/build_package_image.py --platform-name mac",
@@ -93,7 +93,7 @@
         "azslc-1.7.35-rev1-mac": "package-system/azslc-mac",
         "SQLite-3.37.2-rev2-mac": "package-system/SQLite-mac",
         "xxhash-0.7.4-rev1-multiplatform": "package-system/xxhash-multiplatform",
-        "qt-5.15.2-rev7-mac": "package-system/Qt/temp/qt-mac",
+        "qt-5.15.2-rev8-mac": "package-system/Qt/temp/qt-mac",
         "zlib-1.2.11-rev5-mac": "package-system/zlib-mac",
         "zlib-1.2.11-rev5-ios": "package-system/zlib-ios",
         "lz4-1.9.3-vcpkg-rev4-mac": "package-system/lz4-mac",