diff --git a/src/qml/Qt6QmlMacros.cmake b/src/qml/Qt6QmlMacros.cmake index 082e1fe136..045590230e 100644 --- a/src/qml/Qt6QmlMacros.cmake +++ b/src/qml/Qt6QmlMacros.cmake @@ -96,7 +96,14 @@ function(_qt_internal_parse_qml_module_dependency dependency was_marked_as_targe endif() endfunction() -function(_qt_internal_write_qmldir_part target) +function(_qt_internal_write_qmldir_part target qt_cmake_export_namespace) + # _qt_internal_write_qmldir_part is deferred to be called in the root + # CMAKE_BINARY_DIR. If find_package(Qt6) is not called in the root of the project (like in the + # Qt Creator super repo), QT_CMAKE_EXPORT_NAMESPACE will not be defined. + # Manually define it here, based on the value passed to the function, from a scope where it + # is available. + set(QT_CMAKE_EXPORT_NAMESPACE "${qt_cmake_export_namespace}") + set(effective_outdir $) set(qtconf_file "${effective_outdir}/${target}_qt.part.conf") get_target_property(dependency_targets "${target}" QT_QML_DEPENDENT_QML_MODULE_TARGETS) @@ -1124,7 +1131,8 @@ Check https://doc.qt.io/qt-6/qt-cmake-policy-qtp0001.html for policy details." ) cmake_language(EVAL CODE " cmake_language(DEFER DIRECTORY [[${PROJECT_SOURCE_DIR}]] - CALL _qt_internal_write_qmldir_part ${target}) + CALL _qt_internal_write_qmldir_part \"${target}\" + \"${QT_CMAKE_EXPORT_NAMESPACE}\") ") else() # Before CMake 3.19, we don't have DEFER, so we immediately write out the qt.conf @@ -1168,12 +1176,20 @@ Check https://doc.qt.io/qt-6/qt-cmake-policy-qtp0001.html for policy details." if(NOT aotstats_setup_called) set_property(GLOBAL PROPERTY _qt_internal_deferred_aotstats_setup TRUE) cmake_language(EVAL CODE "cmake_language(DEFER DIRECTORY \"${CMAKE_BINARY_DIR}\" " - "CALL _qt_internal_deferred_aotstats_setup)") + "CALL _qt_internal_deferred_aotstats_setup \"${QT_CMAKE_EXPORT_NAMESPACE}\" + )") endif() endif() endfunction() -function(_qt_internal_deferred_aotstats_setup) +function(_qt_internal_deferred_aotstats_setup qt_cmake_export_namespace) + # _qt_internal_deferred_aotstats_setup is deferred to be called in the root + # CMAKE_BINARY_DIR. If find_package(Qt6) is not called in the root of the project (like in the + # Qt Creator super repo), QT_CMAKE_EXPORT_NAMESPACE will not be defined. + # Manually define it here, based on the value passed to the function, from a scope where it + # is available. + set(QT_CMAKE_EXPORT_NAMESPACE "${qt_cmake_export_namespace}") + get_property(module_targets GLOBAL PROPERTY _qt_qml_aotstats_module_targets) set(onlybytecode_modules "") @@ -1206,7 +1222,7 @@ function(_qt_internal_deferred_aotstats_setup) DEPENDS ${aotstats_files} ${module_aotstats_list_file} COMMAND ${tool_wrapper} - $ + $ aggregate ${module_aotstats_list_file} ${output} @@ -1259,13 +1275,13 @@ function(_qt_internal_deferred_aotstats_setup) DEPENDS ${module_aotstats_targets} ${module_aotstats_files} COMMAND ${tool_wrapper} - $ + $ aggregate "${aotstats_list_file}" "${all_aotstats_file}" COMMAND ${tool_wrapper} - $ + $ format "${all_aotstats_file}" "${formatted_stats_file}" diff --git a/tests/auto/cmake/RunCMake/CMakeLists.txt b/tests/auto/cmake/RunCMake/CMakeLists.txt index aac180192f..b4482411fa 100644 --- a/tests/auto/cmake/RunCMake/CMakeLists.txt +++ b/tests/auto/cmake/RunCMake/CMakeLists.txt @@ -5,6 +5,7 @@ _qt_internal_get_cmake_test_configure_options(config_flags) if(NOT CMAKE_CROSSCOMPILING) add_RunCMake_test(qt_target_qml_sources ${config_flags} "-D_Qt6CTestMacros=${_Qt6CTestMacros}") endif() +add_RunCMake_test(export_namespace_in_root ${config_flags}) _qt_internal_get_cmake_test_configure_options(option_list) add_RunCMake_test(generate_qmlls_ini ${option_list}) diff --git a/tests/auto/cmake/RunCMake/export_namespace_in_root/CMakeLists.txt b/tests/auto/cmake/RunCMake/export_namespace_in_root/CMakeLists.txt new file mode 100644 index 0000000000..4860336c72 --- /dev/null +++ b/tests/auto/cmake/RunCMake/export_namespace_in_root/CMakeLists.txt @@ -0,0 +1,5 @@ +cmake_minimum_required(VERSION 3.16) +project(${RunCMake_TEST} LANGUAGES CXX) + +add_subdirectory(Foo/Bar) +add_subdirectory(app) diff --git a/tests/auto/cmake/RunCMake/export_namespace_in_root/Foo/Bar/CMakeLists.txt b/tests/auto/cmake/RunCMake/export_namespace_in_root/Foo/Bar/CMakeLists.txt new file mode 100644 index 0000000000..c1a4c378c5 --- /dev/null +++ b/tests/auto/cmake/RunCMake/export_namespace_in_root/Foo/Bar/CMakeLists.txt @@ -0,0 +1,21 @@ +find_package(Qt6 6.8 REQUIRED COMPONENTS Gui Quick REQUIRED) + +qt_standard_project_setup(REQUIRES 6.8) + +qt_add_qml_module(FooBar + URI Foo.Bar + VERSION 1.0 + STATIC + SOURCES + foobar.h foobar.cpp + QML_FILES + FoobarQML.qml + IMPORTS + QtQuick +) + +target_link_libraries(FooBar + PRIVATE + Qt6::Quick + Qt6::Gui +) diff --git a/tests/auto/cmake/RunCMake/export_namespace_in_root/Foo/Bar/FoobarQML.qml b/tests/auto/cmake/RunCMake/export_namespace_in_root/Foo/Bar/FoobarQML.qml new file mode 100644 index 0000000000..2e33e9aee1 --- /dev/null +++ b/tests/auto/cmake/RunCMake/export_namespace_in_root/Foo/Bar/FoobarQML.qml @@ -0,0 +1,13 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick + +Item { + id: root + + Rectangle { + anchors.fill: root + color: "green" + } +} diff --git a/tests/auto/cmake/RunCMake/export_namespace_in_root/Foo/Bar/foobar.cpp b/tests/auto/cmake/RunCMake/export_namespace_in_root/Foo/Bar/foobar.cpp new file mode 100644 index 0000000000..2dd5ebfd0a --- /dev/null +++ b/tests/auto/cmake/RunCMake/export_namespace_in_root/Foo/Bar/foobar.cpp @@ -0,0 +1,16 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "foobar.h" + +#include + +void Foobar::paint(QPainter *painter) +{ + QPen pen(QColorConstants::Red, 2); + QBrush brush(QColorConstants::Red); + + painter->setPen(pen); + painter->setBrush(brush); + painter->drawRect(0, 0, 100, 100); +} diff --git a/tests/auto/cmake/RunCMake/export_namespace_in_root/Foo/Bar/foobar.h b/tests/auto/cmake/RunCMake/export_namespace_in_root/Foo/Bar/foobar.h new file mode 100644 index 0000000000..799182fc06 --- /dev/null +++ b/tests/auto/cmake/RunCMake/export_namespace_in_root/Foo/Bar/foobar.h @@ -0,0 +1,16 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#pragma once + +#include + +class Foobar : public QQuickPaintedItem +{ + Q_OBJECT + QML_ELEMENT +public: + using QQuickPaintedItem::QQuickPaintedItem; + + void paint(QPainter *painter) override; +}; diff --git a/tests/auto/cmake/RunCMake/export_namespace_in_root/RunCMakeTest.cmake b/tests/auto/cmake/RunCMake/export_namespace_in_root/RunCMakeTest.cmake new file mode 100644 index 0000000000..f0de232d59 --- /dev/null +++ b/tests/auto/cmake/RunCMake/export_namespace_in_root/RunCMakeTest.cmake @@ -0,0 +1,24 @@ +include(RunCMake) + +include(${_Qt6CTestMacros}) +# Stub function to make `_qt_internal_get_cmake_test_configure_options` work +function(_qt_internal_get_build_vars_for_external_projects) +endfunction() + +_qt_internal_get_cmake_test_configure_options(config_flags) +list(APPEND config_flags "-DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH}") + +function(run_cmake_and_build case) + # Set common build directory for configure and build + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${case}-build) + run_cmake_with_options(${case} ${config_flags}) + # Do not remove the current RunCMake_TEST_BINARY_DIR + set(RunCMake_TEST_NO_CLEAN 1) + run_cmake_command(${case}-build ${CMAKE_COMMAND} --build .) +endfunction() + +if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.19" + AND RunCMake_GENERATOR MATCHES "^Ninja" +) + run_cmake_and_build(export_namespace_in_root) +endif() diff --git a/tests/auto/cmake/RunCMake/export_namespace_in_root/app/CMakeLists.txt b/tests/auto/cmake/RunCMake/export_namespace_in_root/app/CMakeLists.txt new file mode 100644 index 0000000000..700536cc41 --- /dev/null +++ b/tests/auto/cmake/RunCMake/export_namespace_in_root/app/CMakeLists.txt @@ -0,0 +1,18 @@ +find_package(Qt6 6.8 COMPONENTS Quick REQUIRED) + +qt_standard_project_setup(REQUIRES 6.8) + +qt_add_executable(app app.cpp) +qt_add_qml_module(app + URI ExampleProjectApp + VERSION 1.0 + QML_FILES Main.qml + DEPENDENCIES + TARGET FooBar +) + +target_link_libraries(app + PRIVATE + Qt6::Quick + FooBarplugin + ) diff --git a/tests/auto/cmake/RunCMake/export_namespace_in_root/app/Main.qml b/tests/auto/cmake/RunCMake/export_namespace_in_root/app/Main.qml new file mode 100644 index 0000000000..33e8aee18f --- /dev/null +++ b/tests/auto/cmake/RunCMake/export_namespace_in_root/app/Main.qml @@ -0,0 +1,29 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick +import Foo.Bar + +Window { + width: 640 + height: 400 + visible: true + title: qsTr("Example Project") + + Foobar { + id: controls + anchors.left: parent.left + anchors.top: parent.top + anchors.margins: 20 + width: 100 + height: 100 + } + FoobarQML { + id: rect + anchors.left: controls.right + anchors.top: parent.top + anchors.margins: 20 + width: 100 + height: 100 + } +} diff --git a/tests/auto/cmake/RunCMake/export_namespace_in_root/app/app.cpp b/tests/auto/cmake/RunCMake/export_namespace_in_root/app/app.cpp new file mode 100644 index 0000000000..48e869459d --- /dev/null +++ b/tests/auto/cmake/RunCMake/export_namespace_in_root/app/app.cpp @@ -0,0 +1,22 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include +#include +#include +#include + +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + + + QDirIterator dirIterator(":/", QDirIterator::Subdirectories); + while (dirIterator.hasNext()) { + qDebug() << dirIterator.next(); + } + QQmlApplicationEngine engine; + engine.loadFromModule("ExampleProjectApp", "Main"); + + return app.exec(); +}