cmake: add IMPORT_PATH to .qmlls.ini

Add the IMPORT_PATH information to .qmlls.ini so that qmlls can use this
information to find the QML modules outside of the build folder, in the
same way as qmllint does.

Collect all the target names whose QT_QML_IMPORT_PATH variable needs to
be added to the .qmlls.ini and print them in the same fashion as the
build path (like the DEPENDENCIES).

Pick-to: 6.8
Fixes: QTBUG-129086
Change-Id: I3840ce11b5cf322af104d99b45d66bfe7e0e5d02
Reviewed-by:  Alexey Edelev <alexey.edelev@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
Sami Shalayel 2024-09-18 15:57:34 +02:00
parent d615e2981b
commit 74af384dcf
9 changed files with 84 additions and 12 deletions

View File

@ -987,6 +987,7 @@ Check https://doc.qt.io/qt-6/qt-cmake-policy-qtp0001.html for policy details."
get_directory_property(_qmlls_ini_build_folders _qmlls_ini_build_folders)
list(APPEND _qmlls_ini_build_folders "${build_folder}")
set_directory_properties(PROPERTIES _qmlls_ini_build_folders "${_qmlls_ini_build_folders}")
set_property(DIRECTORY APPEND PROPERTY _qmlls_ini_import_path_targets "${target}")
# if no call with id 'qmlls_ini_generation_id' was deferred for this directory, do it now
cmake_language(DEFER GET_CALL qmlls_ini_generation_id call)
@ -1134,14 +1135,28 @@ function(_qt_internal_write_deferred_qmlls_ini_file target)
set(qmlls_ini_file "${CMAKE_CURRENT_SOURCE_DIR}/.qmlls.ini")
get_directory_property(_qmlls_ini_build_folders _qmlls_ini_build_folders)
list(REMOVE_DUPLICATES _qmlls_ini_build_folders)
get_directory_property(_qmlls_ini_import_path_targets _qmlls_ini_import_path_targets)
set(_import_paths "")
foreach(import_path_target IN LISTS _qmlls_ini_import_path_targets)
get_target_property(import_path ${import_path_target} QT_QML_IMPORT_PATH)
list(APPEND _import_paths "${import_path}")
endforeach()
if(NOT CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
# replace cmake list separator ';' with unix path separator ':'
string(REPLACE ";" ":" concatenated_build_dirs "${_qmlls_ini_build_folders}")
list(JOIN _import_paths ":" concatenated_import_paths)
else()
# cmake list separator and windows path separator are both ';', so no replacement needed
set(concatenated_build_dirs "${_qmlls_ini_build_folders}")
set(concatenated_import_paths "${_import_paths}")
endif()
_populate_qmlls_ini_file(${target} "${qmlls_ini_file}" "${concatenated_build_dirs}")
_populate_qmlls_ini_file(
${target}
"${qmlls_ini_file}"
"${concatenated_build_dirs}"
"${concatenated_import_paths}")
endfunction()
if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
@ -1154,9 +1169,10 @@ if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
endfunction()
endif()
function(_populate_qmlls_ini_file target qmlls_ini_file concatenated_build_dirs)
function(_populate_qmlls_ini_file target qmlls_ini_file concatenated_build_dirs import_paths)
get_target_property(qtpaths ${QT_CMAKE_EXPORT_NAMESPACE}::qtpaths LOCATION)
_qt_internal_get_tool_wrapper_script_path(tool_wrapper)
add_custom_command(
OUTPUT
${qmlls_ini_file}
@ -1168,6 +1184,7 @@ function(_populate_qmlls_ini_file target qmlls_ini_file concatenated_build_dirs)
${tool_wrapper}
${qtpaths}
--query QT_INSTALL_DOCS >> ${qmlls_ini_file}
COMMAND ${CMAKE_COMMAND} -E echo "importPaths=${import_paths}" >> ${qmlls_ini_file}
COMMENT "Populating .qmlls.ini file"
VERBATIM
)

View File

@ -6,7 +6,7 @@ project(tst_generate_qmlls_ini)
find_package(Qt6 REQUIRED COMPONENTS Core Qml Test)
qt_standard_project_setup()
qt_standard_project_setup(REQUIRES 6.8)
qt_add_executable(tst_generate_qmlls_ini main.cpp)
target_link_libraries(tst_generate_qmlls_ini PRIVATE Qt6::Test)
@ -15,6 +15,8 @@ set(QT_QML_GENERATE_QMLLS_INI ON CACHE BOOL "" FORCE)
add_subdirectory(SomeSubfolder)
add_subdirectory(Dotted)
add_subdirectory(Dependency)
add_subdirectory(ModuleWithDependency)
qt_add_qml_module(tst_generate_qmlls_ini
URI MainModule

View File

@ -0,0 +1,4 @@
# Copyright (C) 2024 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
add_subdirectory(MyDependency)

View File

@ -0,0 +1,7 @@
# Copyright (C) 2024 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
qt_add_qml_module(MyDependency
URI MyDependency
QML_FILES MyItem.qml
)

View File

@ -0,0 +1,3 @@
import QtQuick
Item {}

View File

@ -0,0 +1,4 @@
# Copyright (C) 2024 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
add_subdirectory(MyModule)

View File

@ -0,0 +1,8 @@
# Copyright (C) 2024 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
qt_add_qml_module(MyModule
URI MyModule
DEPENDENCIES TARGET MyDependency
QML_FILES Main.qml
)

View File

@ -0,0 +1,5 @@
import QtQuick
Item {
}

View File

@ -34,7 +34,15 @@ void tst_generate_qmlls_ini::qmllsIniAreCorrect()
QSKIP(u"Cannot find source directory '%1', skipping test..."_s.arg(SOURCE_DIRECTORY)
.toLatin1());
const QString qmllsIniTemplate = uR"([General]
buildDir=%1
no-cmake-calls=false
docDir=%3
importPaths=%4
)"_s;
const QString &docPath = QLibraryInfo::path(QLibraryInfo::DocumentationPath);
const QString emptyImportPath;
{
auto file = QFile(source.absoluteFilePath(qmllsIniName));
QVERIFY(file.exists());
@ -43,8 +51,10 @@ void tst_generate_qmlls_ini::qmllsIniAreCorrect()
auto secondFolder = QDir(build.absolutePath().append(u"/qml/hello/subfolders"_s));
QVERIFY(secondFolder.exists());
QCOMPARE(fileContent,
u"[General]\nbuildDir=%1%2%3\nno-cmake-calls=false\ndocDir=%4\n"_s.arg(build.absolutePath(), QDir::listSeparator(),
secondFolder.absolutePath(), docPath));
qmllsIniTemplate.arg(build.absolutePath()
.append(QDir::listSeparator())
.append(secondFolder.absolutePath()),
docPath, emptyImportPath));
}
{
@ -57,7 +67,7 @@ void tst_generate_qmlls_ini::qmllsIniAreCorrect()
QVERIFY(file.open(QFile::ReadOnly | QFile::Text));
const auto fileContent = QString::fromUtf8(file.readAll());
QCOMPARE(fileContent,
u"[General]\nbuildDir=%1\nno-cmake-calls=false\ndocDir=%2\n"_s.arg(buildSubfolder.absolutePath(), docPath));
qmllsIniTemplate.arg(buildSubfolder.absolutePath(), docPath, emptyImportPath));
}
}
@ -70,9 +80,8 @@ void tst_generate_qmlls_ini::qmllsIniAreCorrect()
QVERIFY(file.exists());
QVERIFY(file.open(QFile::ReadOnly | QFile::Text));
const auto fileContent = QString::fromUtf8(file.readAll());
QCOMPARE(
fileContent,
u"[General]\nbuildDir=%1\nno-cmake-calls=false\ndocDir=%2\n"_s.arg(build.absolutePath(), docPath));
QCOMPARE(fileContent,
qmllsIniTemplate.arg(build.absolutePath(), docPath, emptyImportPath));
}
}
{
@ -86,9 +95,22 @@ void tst_generate_qmlls_ini::qmllsIniAreCorrect()
QVERIFY(file.exists());
QVERIFY(file.open(QFile::ReadOnly | QFile::Text));
const auto fileContent = QString::fromUtf8(file.readAll());
QCOMPARE(
fileContent,
u"[General]\nbuildDir=%1\nno-cmake-calls=false\ndocDir=%2\n"_s.arg(build.absolutePath(), docPath));
QCOMPARE(fileContent,
qmllsIniTemplate.arg(build.absolutePath(), docPath, emptyImportPath));
}
}
{
QDir dottedUriSubfolder = source;
QVERIFY(dottedUriSubfolder.cd(u"ModuleWithDependency"_s));
QVERIFY(dottedUriSubfolder.cd(u"MyModule"_s));
{
auto file = QFile(dottedUriSubfolder.absoluteFilePath(qmllsIniName));
QVERIFY(file.exists());
QVERIFY(file.open(QFile::ReadOnly | QFile::Text));
const auto fileContent = QString::fromUtf8(file.readAll());
QCOMPARE(fileContent,
qmllsIniTemplate.arg(build.absoluteFilePath(u"ModuleWithDependency"_s),
docPath, build.absoluteFilePath(u"Dependency"_s)));
}
}
}