Make sure that module can be imported by the provided QML import path

When resolving QML module dependencies we scan the produced by the
build system import paths for the required QML modules. Previously the
check in androiddeployqt only was confirming that the required import
starts with the one of import paths. This worked well unless the
required import is nested in higher level import path. In the situation
when we have the following build structure:
  build_dir/
    imports/
       MyModule/
          ...
and both 'build_dir' and 'build_dir/imports' directories are in QML
import paths, the MyModule QML module is resolved by the
'build_dir/imports'. But androiddeployqt assumed that it's found by
'build_dir' import path and copied the whole 'imports' directory as
the 'MyModule' QML module. The resulting bundle then had the
following content:
  qml/
    imports/
      MyModule/
        ...
  ...
instead of the correct one:
  qml/
    MyModule/
      ...
  ...

This checks if import path contains the required url-based module
path before using it as the base directory to copy the module.

Amends 0a73fb10005053945571e6cdb0b03d916715c112

Fixes: QTBUG-108194
Change-Id: I79e1a8a67f62e5ae4a899ba1a4f49ee4ad44ebf9
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Dominik Holland <dominik.holland@qt.io>
(cherry picked from commit 10372c074bf2975ccb5e4afd3bba0f2738e0a1d5)
Reviewed-by: Zoltan Gera <zoltan.gera@qt.io>
This commit is contained in:
Alexey Edelev 2022-11-07 16:35:42 +01:00
parent 105e53b62b
commit f71c4df4b2

View File

@ -1932,7 +1932,7 @@ bool readDependenciesFromElf(Options *options,
bool goodToCopy(const Options *options, const QString &file, QStringList *unmetDependencies);
bool checkCanImportFromRootPaths(const Options *options, const QString &absolutePath,
const QUrl &moduleUrl);
const QString &moduleUrlPath);
bool scanImports(Options *options, QSet<QString> *usedDependencies)
{
@ -2072,7 +2072,8 @@ bool scanImports(Options *options, QSet<QString> *usedDependencies)
const QUrl url(object.value("name"_L1).toString());
if (checkCanImportFromRootPaths(options, info.absolutePath(), url)) {
const QString moduleUrlPath = u"/"_s + url.toString().replace(u'.', u'/');
if (checkCanImportFromRootPaths(options, info.absolutePath(), moduleUrlPath)) {
if (options->verbose)
fprintf(stdout, " -- Skipping because path is in QML root path.\n");
continue;
@ -2080,13 +2081,8 @@ bool scanImports(Options *options, QSet<QString> *usedDependencies)
QString importPathOfThisImport;
for (const QString &importPath : qAsConst(importPaths)) {
#if defined(Q_OS_WIN32)
Qt::CaseSensitivity caseSensitivity = Qt::CaseInsensitive;
#else
Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive;
#endif
QString cleanImportPath = QDir::cleanPath(importPath);
if (info.absoluteFilePath().startsWith(cleanImportPath, caseSensitivity)) {
if (QFile::exists(cleanImportPath + moduleUrlPath)) {
importPathOfThisImport = importPath;
break;
}
@ -2165,11 +2161,10 @@ bool scanImports(Options *options, QSet<QString> *usedDependencies)
}
bool checkCanImportFromRootPaths(const Options *options, const QString &absolutePath,
const QUrl &moduleUrl)
const QString &moduleUrlPath)
{
const QString pathFromUrl = u"/"_s + moduleUrl.toString().replace(u'.', u'/');
for (auto rootPath : options->rootPaths) {
if ((rootPath + pathFromUrl) == absolutePath)
if ((rootPath + moduleUrlPath) == absolutePath)
return true;
}
return false;