From 74c55fe6d87d94bb83f1a13da45f3599e5708297 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Burak=20Han=C3=A7erli?= <burak.hancerli@qt.io>
Date: Thu, 23 Jan 2025 14:34:05 +0000
Subject: [PATCH] Remove importdummy dependency

---
 src/CMakeLists.txt          | 104 ++++++++++++++++++++++++++++++++++--
 src/backend/importdummy.qml |  45 ----------------
 2 files changed, 101 insertions(+), 48 deletions(-)
 delete mode 100644 src/backend/importdummy.qml

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 4330115..327a9b6 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,13 +1,108 @@
 find_package(
     Qt6
-    COMPONENTS Core Widgets Quick Gui Qml Multimedia MultimediaWidgets Concurrent Network WebSockets
+    COMPONENTS
+        Core Widgets Quick Gui Qml Multimedia MultimediaWidgets Concurrent Network WebSockets
+        TextToSpeech Location Sensors WebView Positioning
     REQUIRED
 )
 
-find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core Network WebSockets)
+find_package(
+    QT NAMES Qt6 Qt5 REQUIRED
+    COMPONENTS
+        Core Network WebSockets TextToSpeech Location Sensors WebView Positioning)
+
+# In shared Qt builds, the qml plugins don't have dependencies on their backing libraries, and
+# thus the backing library packages are not automatically looked up.
+# The StandaloneTests directory contains Config files that find_package all installed Qt packages.
+# Abuse that, and include all of them to make all the backing libraries available as imported
+# targets.
+find_package(Qt6 COMPONENTS BuildInternals)
+if(Qt6BuildInternals_DIR)
+    set(standalone_tests_dir "${Qt6BuildInternals_DIR}/StandaloneTests")
+    if(EXISTS "${standalone_tests_dir}")
+        # Glob the config files in there.
+        file(GLOB_RECURSE standalone_tests_files "${standalone_tests_dir}/*TestsConfig.cmake")
+
+        # Include each one of them.
+        foreach(standalone_tests_file IN LISTS standalone_tests_files)
+            include("${standalone_tests_file}")
+        endforeach()
+    endif()
+endif()
+
+set(imports "")
+
+# Get all imported targets.
+get_property(imported_targets DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY IMPORTED_TARGETS)
+
+# Horrible hack for shared qt builds, to ensure we bundle all known shared library qml plugins.
+# Do that by finding all qml modules, their plugins, the location of the plugins, then finding the
+# path to the qmldir files of the plugins, extract the module name, and adding it as an import
+# statement into a dynamically generated qml file.
+foreach(imported_target IN LISTS imported_targets)
+    # Get all qml module targets, they would have the _qt_qml_module_installed_plugin_target
+    # property set.
+    get_target_property(qml_plugin_target "${imported_target}"
+        _qt_qml_module_installed_plugin_target)
+
+    if(qml_plugin_target)
+        message(STATUS
+            "Imported target: ${imported_target} -> ${qml_plugin_target}")
+
+        # Get location of the plugin file.
+        get_target_property(imported_location "${qml_plugin_target}" IMPORTED_LOCATION)
+        if(NOT EXISTS "${imported_location}")
+            continue()
+        endif()
+
+        # Get parent dir of the plugin file.
+        get_filename_component(imported_location_dir "${imported_location}" DIRECTORY)
+
+        # Build path to qmldir in the same directory. We assume the qmldir is always next
+        # to the plugin file. That's at least usually the case for Qt qml plugins.
+        set(qmldir_path "${imported_location_dir}/qmldir")
+        if(NOT EXISTS "${qmldir_path}")
+            continue()
+        endif()
+
+        # Read qmldir file contents.
+        file(READ "${qmldir_path}" qmldir_content)
+        if(qmldir_content STREQUAL "")
+            continue()
+        endif()
+
+        # Find the module name in the qmldir file
+        string(REGEX MATCH "module ([^\n]+)" module_match "${qmldir_content}")
+        if(CMAKE_MATCH_1)
+            # Add the module name as an import to the imports list
+            list(APPEND imports "import ${CMAKE_MATCH_1}")
+        endif()
+    endif()
+endforeach()
+
+set(imports_file_path "${CMAKE_CURRENT_BINARY_DIR}/dynamic_imports.qml")
+
+# Needed to stop __qt_get_relative_resource_path_for_file from erroring out.
+set_source_files_properties("${imports_file_path}"
+    PROPERTIES QT_RESOURCE_ALIAS  "dynamic_imports.qml")
+if(imports)
+    list(REMOVE_DUPLICATES imports)
+    string(REPLACE ";" "\n" imports "${imports}")
+endif()
+
+# Use file(GENERATE) to prevent touching the file if the contents hasn't changed.
+set(dummy_valid_content "ApplicationWindow {
+    visible: true
+    width: 640
+    height: 480
+}")
+
+file(GENERATE OUTPUT "${imports_file_path}" CONTENT "${imports}
+
+${dummy_valid_content}
+")
 
 qt_add_executable(${PROJECT_NAME}
-    backend/importdummy.qml
     backend/main.cpp
     backend/logger.h
     backend/backend.cpp backend/backend.h
@@ -27,6 +122,7 @@ qt_add_qml_module(${PROJECT_NAME}
     URI AndroidUI
     VERSION 1.0
     QML_FILES
+        "${imports_file_path}"
         Constants.qml
         HomePage.qml
         Main.qml
@@ -52,6 +148,8 @@ target_link_libraries(${PROJECT_NAME} PRIVATE
     Qt6::Qml Qt6::GuiPrivate
     Qt6::Multimedia Qt6::MultimediaWidgets
     Qt6::Concurrent Qt6::Network Qt6::WebSockets
+    Qt6::TextToSpeech Qt6::Location Qt6::Sensors
+    Qt6::WebView Qt6::Positioning
     ZXing::ZXing
 )
 
diff --git a/src/backend/importdummy.qml b/src/backend/importdummy.qml
deleted file mode 100644
index f6836ef..0000000
--- a/src/backend/importdummy.qml
+++ /dev/null
@@ -1,45 +0,0 @@
-// Hack to force the qml plugins to be linked statically
-
-import QtQuick
-import QtQuick.Controls
-
-import QtQml
-import QtQml.Models
-import QtQml.StateMachine
-
-import QtQuick3D
-import QtQuick3D.AssetUtils
-import QtQuick3D.Effects
-import QtQuick3D.Helpers
-import QtQuick3D.ParticleEffects
-import QtQuick3D.Particles3D
-import QtQuick.VirtualKeyboard
-
-import QtQuick.Studio.Application
-import QtQuick.Studio.Components
-import QtQuick.Studio.Effects
-import QtQuick.Studio.EventSimulator
-import QtQuick.Studio.EventSystem
-import QtQuick.Studio.LogicHelper
-import QtQuick.Studio.MultiText
-import QtQuick.Studio.Utils
-import QtQuick.Studio.DesignEffects
-
-import QtQuick.Timeline
-import QtQuick.Timeline.BlendTrees
-
-import QtQuickUltralite.Extras
-import QtQuickUltralite.Layers
-
-import QtCharts
-
-import FlowView
-import Qt.labs.folderlistmodel
-
-import QtWebSockets
-
-ApplicationWindow {
-    visible: true
-    width: 640
-    height: 480
-}
-- 
GitLab