aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
authorCraig Scott <craig.scott@qt.io>2021-08-16 15:10:38 +1000
committerCraig Scott <craig.scott@qt.io>2021-08-20 09:29:30 +1000
commita25f650c317e4886007a8beb0e9f2f7e973e6e7c (patch)
tree575ecdbf3bf260af31eef3c5df4adc45556d789b /src/qml
parent30e6bb35e48207a994dd4e49ca999d45266a04f5 (diff)
Allow QML plugin's CMake target name to be specified for qmldir file
The current code assumes that the basename of the QML plugin is the same as the CMake target it corresponds to. This won't be the case for installed Qt packages due to the installed name including a namespace. It also won't match when a Qt library infix is used. The current code works around the former by trying to heuristically work out whether a namespaced Qt target exists for the plugin. The Qt library infix is more problematic because the plugin target name won't include the infix whereas the plugin library basename will. Address both of those issues by adding an internal option INSTALLED_PLUGIN_TARGET to qt6_add_qml_module() which allows the installed target name to be provided. When included in a qmldir file, qt6_import_qml_plugin() will use that name, otherwise it will fall back to using the plugin library's basename, as per the current behavior. The option may become public in the future, but for now it is only for Qt's internal use for the 6.2 release. Fixes: QTBUG-95140 Pick-to: 6.2 Change-Id: I5a057c80b70ee802c0f0840e9eea2e579193d126 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/Qt6QmlBuildInternals.cmake28
-rw-r--r--src/qml/Qt6QmlMacros.cmake48
-rw-r--r--src/qml/qmldirparser/qqmldirparser.cpp19
-rw-r--r--src/qml/qmldirparser/qqmldirparser_p.h2
4 files changed, 77 insertions, 20 deletions
diff --git a/src/qml/Qt6QmlBuildInternals.cmake b/src/qml/Qt6QmlBuildInternals.cmake
index 3b9e99c782..f979c9f656 100644
--- a/src/qml/Qt6QmlBuildInternals.cmake
+++ b/src/qml/Qt6QmlBuildInternals.cmake
@@ -197,6 +197,8 @@ function(qt_internal_add_qml_module target)
)
endif()
+ set(add_qml_module_args "")
+
if(NOT arg_NO_PLUGIN AND NOT arg_NO_CREATE_PLUGIN_TARGET)
# If the qt_internal_add_qml_module call didn't specify a CLASS_NAME, we need to pre-compute
# it here and pass it along to qt_internal_add_plugin -> qt_add_plugin so that
@@ -217,6 +219,28 @@ function(qt_internal_add_qml_module target)
qt_internal_add_plugin(${arg_PLUGIN_TARGET} ${plugin_args})
+ # Get the last dot-separated part of the URI. There should only be one
+ # plugin library in the output directory, so we shouldn't need to
+ # include the full URI namespace.
+ string(REGEX REPLACE "^(.*\\.)?([^.]+)$" "\\2" plugin_basename "${arg_URI}")
+ # Add the infix and "plugin", lowercase that and use it as the basename
+ # of the plugin library.
+ string(TOLOWER "${plugin_basename}${QT_LIBINFIX}plugin" plugin_basename)
+ set_target_properties(${arg_PLUGIN_TARGET} PROPERTIES
+ OUTPUT_NAME "${plugin_basename}"
+ )
+
+ get_target_property(export_name ${arg_PLUGIN_TARGET} EXPORT_NAME)
+ if(export_name)
+ list(APPEND add_qml_module_args
+ INSTALLED_PLUGIN_TARGET "${QT_CMAKE_EXPORT_NAMESPACE}::${export_name}"
+ )
+ else()
+ list(APPEND add_qml_module_args
+ INSTALLED_PLUGIN_TARGET "${QT_CMAKE_EXPORT_NAMESPACE}::${arg_PLUGIN_TARGET}"
+ )
+ endif()
+
if(NOT arg_PLUGIN_TARGET STREQUAL target)
get_target_property(lib_type ${arg_PLUGIN_TARGET} TYPE)
if(lib_type STREQUAL "STATIC_LIBRARY")
@@ -254,10 +278,6 @@ function(qt_internal_add_qml_module target)
endif()
endforeach()
- if(QT_LIBINFIX)
- list(APPEND add_qml_module_args __QT_INTERNAL_QT_LIBINFIX "${QT_LIBINFIX}")
- endif()
-
# Update the backing and plugin targets with qml-specific things.
qt6_add_qml_module(${target}
${add_qml_module_args}
diff --git a/src/qml/Qt6QmlMacros.cmake b/src/qml/Qt6QmlMacros.cmake
index d2a40a2065..0f3aff5291 100644
--- a/src/qml/Qt6QmlMacros.cmake
+++ b/src/qml/Qt6QmlMacros.cmake
@@ -28,6 +28,7 @@ function(qt6_add_qml_module target)
set(args_single
PLUGIN_TARGET
+ INSTALLED_PLUGIN_TARGET # Internal option only, it may be removed
OUTPUT_TARGETS
RESOURCE_PREFIX
URI
@@ -42,7 +43,6 @@ function(qt6_add_qml_module target)
RESOURCE_EXPORT
INSTALL_DIRECTORY
INSTALL_LOCATION
- __QT_INTERNAL_QT_LIBINFIX # Used only by _qt_internal_target_generate_qmldir()
)
set(args_multi
@@ -235,6 +235,9 @@ function(qt6_add_qml_module target)
# The plugin can't be optional when it has no backing target
set(arg_NO_PLUGIN_OPTIONAL TRUE)
endif()
+ if(NOT arg_INSTALLED_PLUGIN_TARGET)
+ set(arg_INSTALLED_PLUGIN_TARGET ${arg_PLUGIN_TARGET})
+ endif()
set(no_gen_source)
if(arg_NO_GENERATE_PLUGIN_SOURCE)
@@ -409,8 +412,8 @@ function(qt6_add_qml_module target)
QT_QML_MODULE_TARGET_PATH "${arg_TARGET_PATH}"
QT_QML_MODULE_VERSION "${arg_VERSION}"
QT_QML_MODULE_CLASS_NAME "${arg_CLASS_NAME}"
- QT_QML_MODULE_LIBINFIX "${arg___QT_INTERNAL_QT_LIBINFIX}"
QT_QML_MODULE_PLUGIN_TARGET "${arg_PLUGIN_TARGET}"
+ QT_QML_MODULE_INSTALLED_PLUGIN_TARGET "${arg_INSTALLED_PLUGIN_TARGET}"
QT_QML_MODULE_DESIGNER_SUPPORTED "${arg_DESIGNER_SUPPORTED}"
QT_QML_MODULE_OUTPUT_DIRECTORY "${arg_OUTPUT_DIRECTORY}"
QT_QML_MODULE_RESOURCE_PREFIX "${qt_qml_module_resource_prefix}"
@@ -835,6 +838,8 @@ function(_qt_internal_target_generate_qmldir target)
endif()
set(content "module ${uri}\n")
+ _qt_internal_qmldir_item(linktarget QT_QML_MODULE_INSTALLED_PLUGIN_TARGET)
+
get_target_property(plugin_target ${target} QT_QML_MODULE_PLUGIN_TARGET)
if(plugin_target)
get_target_property(no_plugin_optional ${target} QT_QML_MODULE_NO_PLUGIN_OPTIONAL)
@@ -842,8 +847,16 @@ function(_qt_internal_target_generate_qmldir target)
string(APPEND content "optional ")
endif()
- get_target_property(qt_libinfix ${target} QT_QML_MODULE_LIBINFIX)
- string(APPEND content "plugin ${plugin_target}${qt_libinfix}\n")
+ set(plugin_basename)
+ if(TARGET ${plugin_target})
+ get_target_property(plugin_basename ${plugin_target} OUTPUT_NAME)
+ endif()
+ if(plugin_basename)
+ string(APPEND content "plugin ${plugin_basename}\n")
+ else()
+ string(APPEND content "plugin ${plugin_target}\n")
+ endif()
+
_qt_internal_qmldir_item(classname QT_QML_MODULE_CLASS_NAME)
endif()
@@ -1877,7 +1890,8 @@ but this file does not exist. Possible reasons include:
set(entry_name "qml_import_scanner_import_${idx}")
cmake_parse_arguments("entry"
""
- "CLASSNAME;NAME;PATH;PLUGIN;RELATIVEPATH;TYPE;VERSION;" ""
+ "CLASSNAME;NAME;PATH;PLUGIN;RELATIVEPATH;TYPE;VERSION;LINKTARGET"
+ ""
${${entry_name}}
)
endmacro()
@@ -1968,18 +1982,20 @@ but this file does not exist. Possible reasons include:
# (typically brought in via find_package(Qt6...) ).
# For other plugins, the targets can come from the project itself.
#
- # Handles Qt provided Qml plugins
- if(TARGET "${QT_CMAKE_EXPORT_NAMESPACE}::${entry_PLUGIN}")
- set(plugin_target "${QT_CMAKE_EXPORT_NAMESPACE}::${entry_PLUGIN}")
- list(APPEND plugins_to_link "${plugin_target}")
-
- # Handles user project provided Qml plugins
- elseif(TARGET ${entry_PLUGIN} AND TARGET ${entry_PLUGIN}_init)
- set(plugin_target "${entry_PLUGIN}")
- list(APPEND plugins_to_link "${plugin_target}")
-
- # TODO: QTBUG-94605 Figure out if this is a reasonable scenario to support
+ if(entry_LINKTARGET)
+ if(TARGET ${entry_LINKTARGET})
+ list(APPEND plugins_to_link "${entry_LINKTARGET}")
+ else()
+ message(WARNING
+ "The qml plugin '${entry_PLUGIN}' is a dependency of '${target}', "
+ "but the link target it defines (${entry_LINKTARGET}) does not exist "
+ "in the current scope. The plugin will not be linked."
+ )
+ endif()
+ elseif(TARGET ${entry_PLUGIN})
+ list(APPEND plugins_to_link "${entry_PLUGIN}")
else()
+ # TODO: QTBUG-94605 Figure out if this is a reasonable scenario to support
message(WARNING
"The qml plugin '${entry_PLUGIN}' is a dependency of '${target}', "
"but there is no target by that name in the current scope. The plugin will "
diff --git a/src/qml/qmldirparser/qqmldirparser.cpp b/src/qml/qmldirparser/qqmldirparser.cpp
index 86d3972b4b..183fa918d2 100644
--- a/src/qml/qmldirparser/qqmldirparser.cpp
+++ b/src/qml/qmldirparser/qqmldirparser.cpp
@@ -85,6 +85,7 @@ void QQmlDirParser::clear()
_designerSupported = false;
_typeInfos.clear();
_classNames.clear();
+ _linkTarget.clear();
}
inline static void scanSpace(const QChar *&ch) {
@@ -321,6 +322,24 @@ bool QQmlDirParser::parse(const QString &source)
}
_preferredPath = sections[1];
+ } else if (sections[0] == QLatin1String("linktarget")) {
+ if (sectionCount < 2) {
+ reportError(lineNumber, 0,
+ QStringLiteral("linktarget directive requires an argument, "
+ "but %1 were provided")
+ .arg(sectionCount - 1));
+ continue;
+ }
+
+ if (!_linkTarget.isEmpty()) {
+ reportError(
+ lineNumber, 0,
+ QStringLiteral(
+ "only one linktarget directive may be defined in a qmldir file"));
+ continue;
+ }
+
+ _linkTarget = sections[1];
} else if (sectionCount == 2) {
// No version specified (should only be used for relative qmldir files)
const Component entry(sections[0], sections[1], QTypeRevision());
diff --git a/src/qml/qmldirparser/qqmldirparser_p.h b/src/qml/qmldirparser/qqmldirparser_p.h
index 8940fb1313..fe371e6b4f 100644
--- a/src/qml/qmldirparser/qqmldirparser_p.h
+++ b/src/qml/qmldirparser/qqmldirparser_p.h
@@ -161,6 +161,7 @@ public:
QStringList typeInfos() const { return _typeInfos; }
QStringList classNames() const { return _classNames; }
QString preferredPath() const { return _preferredPath; }
+ QString linkTarget() const { return _linkTarget; }
private:
bool maybeAddComponent(const QString &typeName, const QString &fileName, const QString &version, QHash<QString,Component> &hash, int lineNumber = -1, bool multi = true);
@@ -178,6 +179,7 @@ private:
bool _designerSupported = false;
QStringList _typeInfos;
QStringList _classNames;
+ QString _linkTarget;
};
using QQmlDirComponents = QMultiHash<QString,QQmlDirParser::Component>;