From aad4158959890b72afdd062614c1142c100c65b5 Mon Sep 17 00:00:00 2001 From: Alexandru Croitor Date: Wed, 13 Oct 2021 16:08:45 +0200 Subject: [PATCH] CMake: Postpone target existence check for qml plugin targets Each included qml Qt6FooPluginTargets.cmake file checks whether all the dependency targets that are referenced in the file already exist by the time the file is included. If one of the referenced targets is missing, the file sets ${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE with a message mentioning which targets are missing and also sets ${CMAKE_FIND_PACKAGE_NAME}_FOUND to FALSE. All our qml package Config.cmake and Targets.cmake files are include()d by Qt6QmlPlugins.cmake using a file(GLOB) which means the order in which the files are loaded is implementation-defined. Furthermore we didn't check the above set variables after each inclusion, which means the values are overridden and the last plugin to be loaded determines whether the Qml package is found or not. If the last included file sets no error, it effectively silences any previously set error. Ever since we added dependencies between the qml plugin targets themselves, we hit the above situation and depending on the platform, no error was shown because the last file overrode any errors. But we finally got a specific platform (wasm) which unearthed the problem (QTBUG-97478). This can happen for any static Qt build though. To fix this properly, we will most likely have to rewrite the whole inclusion mechanism to use find_package() so that dependencies can be resolved recursively as needed. This is a non-trivial change that will have to be addressed in both qtbase and qtdeclarative. In the mean time, a stop-gap solution that this change implements is to include all the files while ignoring any error messages. Then include the files one more time and check for error message after each included file. All qml plugin targets should have been brought into scope with the first round of inclusions, thus circumventing "missing referenced target" errors, while still catching any other possible errors. Amends 6fd1216801f078f65be2cbc748cc459cb6912a4f 9fc302e6d146878103b3d105dce49c7695fcf93a c368175a9e0a0c120b5bb8a0a02859bfc0cf42ba in qtdeclarative. Pick-to: 6.2 6.2.1 Fixes: QTBUG-97478 Task-number: QTBUG-95609 Task-number: QTBUG-97099 Change-Id: I157fa93fc979d726cd221d969b995b3642aeec77 Reviewed-by: Qt CI Bot Reviewed-by: Fabian Kosmale Reviewed-by: Alexey Edelev --- cmake/QtPostProcessHelpers.cmake | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/cmake/QtPostProcessHelpers.cmake b/cmake/QtPostProcessHelpers.cmake index ba564dbae7..35ca6eabee 100644 --- a/cmake/QtPostProcessHelpers.cmake +++ b/cmake/QtPostProcessHelpers.cmake @@ -410,11 +410,40 @@ function(qt_internal_create_plugins_files) if(QT_MODULE STREQUAL "Qml") set(QT_MODULE_PLUGIN_INCLUDES "${QT_MODULE_PLUGIN_INCLUDES} +# Qml plugin targets might have dependencies on other qml plugin targets, but the Targets.cmake +# files are included in the order that file(GLOB) returns, which means certain targets that are +# referenced might not have been created yet, and \${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE +# might be set to a message saying those targets don't exist. +# +# Postpone checking of which targets don't exist until all Qml PluginConfig.cmake files have been +# included, by including all the files one more time and checking for errors at each step. +# +# TODO: Find a better way to deal with this, perhaps by using find_package() instead of include +# for the Qml PluginConfig.cmake files. + file(GLOB __qt_qml_plugins_config_file_list \"\${CMAKE_CURRENT_LIST_DIR}/QmlPlugins/${INSTALL_CMAKE_NAMESPACE}*Config.cmake\") if (__qt_qml_plugins_config_file_list AND NOT QT_SKIP_AUTO_QML_PLUGIN_INCLUSION) + # First round of inclusions ensure all qml plugin targets are brought into scope. foreach(__qt_qml_plugin_config_file \${__qt_qml_plugins_config_file_list}) include(\${__qt_qml_plugin_config_file}) + + # Temporarily unset any failure markers. + unset(\${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE) + unset(\${CMAKE_FIND_PACKAGE_NAME}_FOUND) endforeach() + + # For the second round of inclusions, check and bail out early if there are errors. + foreach(__qt_qml_plugin_config_file \${__qt_qml_plugins_config_file_list}) + include(\${__qt_qml_plugin_config_file}) + + if(\${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE) + string(APPEND \${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE + \"\nThe message was set in \${__qt_qml_plugin_config_file} \") + set(\${CMAKE_FIND_PACKAGE_NAME}_FOUND FALSE) + return() + endif() + endforeach() + endif()") endif()