Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qt6-port-to-qt-add-qml-module.qdoc
Go to the documentation of this file.
1// Copyright (C) 2025 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
3
4/*!
5\page qt6-port-to-qt-add-qml-module.html
6\title Port QML modules to CMake
7\brief Port your QML modules to the qt_add_qml_module CMake API.
8
9QML modules have become more powerful and easier to use in Qt 6. The following sections describe
10how to port QML modules to the \l qt_add_qml_module CMake API.
11
12See also \l{Modern QML modules} on how to modernize a QML module that already uses \l
13qt_add_qml_module.
14
15\section1 Identify issues to fix
16
17Use \l qmllint to support you through the process.
18
19Each QML module defined with \l qt_add_qml_module has a \c{_qmllint} CMake target that you can
20use to identify potential issues or improvements. For a QML module called \c MyQmlLibrary use
21\c{MyQmlLibrary_qmllint}, for example. To run \l qmllint on all QML modules, use \c
22{all_qmllint}.
23
24The warning categories of \l qmllint that hint at QML module issues are:
25\list
26 \li \l{Warnings occurred while importing}{[import]}
27 \li \l{Unused imports}{[unused-imports]}
28 \li \l{Unresolved type}{[unresolved-type]}
29 \li \l{Unresolved Alias}{[unresolved-alias]}
30 \li \l{Missing enum entry}{[missing-enum-entry]}
31 \li \l{Missing property}{[missing-property]}
32 \li \l{Missing type}{[missing-type]}
33\endlist
34
35\section1 Prepare the project for qt_add_qml_module
36
37\section2 Make qt_add_qml_module available in CMake
38
39To make \l qt_add_qml_module available in CMake, add \c Core and \c Qml to your \c find_package
40call in the project's top-level \c CMakeLists.txt file:
41\badcode
42find_package(Qt6 REQUIRED COMPONENTS Core Qml)
43\endcode
44
45\section2 Use qt_standard_project_setup
46
47\l qt_standard_project_setup sets up \l{Qt CMake policies} needed for \l qt_add_qml_module, among
48other things.
49
50Call \l qt_standard_project_setup in the project's top-level \c CMakeLists.txt file
51before any \l qt_add_qml_module call:
52\badcode
53qt_standard_project_setup(REQUIRES 6.8)
54\endcode
55
56\section1 Use qt_add_qml_module
57
58\l qt_add_qml_module is the CMake function that takes care of generating QML modules. It
59automatically generates \c qmldir and \c qmltypes files, and sets up tooling like \l qmlcachegen
60or \l qmllint.
61
62QML modules can be added to both executable and library targets in CMake. QML modules attached
63to the executable target can't be used or linked by other executables, while QML modules attached
64to library targets can.
65
66\section2 Add a QML module to your executable target
67In this case, the source files of the QML module are treated as part of the executable itself,
68rather than being compiled into a separate library. This means neither a module nor plugin library
69for this module is created—--the module is fully integrated into the executable. As a result, the
70module is tied to that specific program and cannot be reused by other executables or libraries.
71
72To add a QML module to your executable, in your \c CMakeLists.txt:
73\badcode
74# pre-existing:
75qt_add_executable(MyApp main.cpp)
76
77# add this
78qt_add_qml_module(MyApp
79 URI MyAppModule
80 QML_FILES
81 Main.qml # and possibly more .qml files
82)
83\endcode
84
85The \c Main.qml should start with an upper case letter so that it can be instantiated by
86\c loadFromModule methods like \l{QQmlApplicationEngine::loadFromModule} or
87\l{QQmlComponent::loadFromModule}.
88Also, the QML module URI should be different from the target name to avoid name clashes
89in the build folder.
90
91\section2 Add a QML module to your library target
92To add a QML module to your library, in your \c CMakeLists.txt:
93\badcode
94qt_add_qml_module(MyQmlLibrary
95 URI MyQmlModule
96 QML_FILES MyQmlComponent1.qml MyQmlComponent2.qml...
97 SOURCES MyCppComponent1.h MyCppComponent1.cpp MyCppComponent2.h MyCppComponent2.cpp...
98 RESOURCES MyResource1.png MyResource2.png...
99)
100\endcode
101
102\l qt_add_qml_module creates a \c SHARED library via \l qt_add_library if the \c
103MyQmlLibrary target does not exist yet, like in this example.
104
105\note Your QML module URI should be different from the target name to avoid name clashes in the
106build folder.
107
108\section1 Use loadFromModule to load your QML files
109
110Use \c loadFromModule to load your QML file, for example:
111\badcode
112engine.load(QUrl(QStringLiteral("qrc:/MyQmlModule/Main.qml")));
113// becomes
114engine.loadFromModule("MyQmlModule", "Main");
115\endcode
116
117\section1 Remove handwritten qmldir files
118
119\l qt_add_qml_module automatically generates \c qmldir files. If you have singletons in
120your \c qmldir, declare them in your \c CMakeLists.txt before the \l qt_add_qml_module call with:
121\badcode
122set_source_files_properties(MySingleton.qml PROPERTIES QT_QML_SINGLETON_TYPE TRUE)
123\endcode
124
125Delete the handwritten \c qmldir after that.
126
127\section1 Remove qmltypes files generated by qmlplugindump
128
129\l qt_add_qml_module auto-generates \c qmltypes files when all your types are using
130\l{Registering C++ Types with the QML Type System}{declarative type registration}, which removes
131the need to generate \c qmltypes files by hand using tools like \c qmlplugindump.
132
133To achieve that, remove manual calls to \c qmlRegisterType and its variants. Then,
134\l{Registering C++ Types with the QML Type System}{register your types declaratively} by using
135\l QML_ELEMENT, for example:
136\badcode
137// add this header
138#include <QtQml/qqmlregistrations.h>
139
140class MyComponent: public QObject {
141 Q_OBJECT
142
143 // add this line to register MyComponent as 'MyComponent' in QML.
144 QML_ELEMENT
145 ....
146};
147\endcode
148
149See \l{Registering C++ Types with the QML Type System} on how to handle more complicated
150registration cases like foreign type registration.
151
152Delete the handwritten \c qmltypes files after that.
153
154\section1 Remove handwritten type registration plugins
155
156\l qt_add_qml_module can generate a \l {Creating C++ Plugins for QML}{QML module plugin}
157automatically for you. You don't need a handwritten plugin if your plugin's only task is to do type
158registration. Remove the plugin altogether if switching to declarative type registration did remove
159all the code from your plugin.
160
161Make sure that you \e remove the \c NO_PLUGIN, \c NO_PLUGIN_OPTIONAL, \c
162NO_CREATE_PLUGIN_TARGET, and \c NO_GENERATE_PLUGIN_SOURCE arguments from \l qt_add_qml_module to
163allow automatic plugin generation.
164
165\section1 Remove qrc files
166
167\l qt_add_qml_module automatically generates \c qrc files. To list resources in the \c qrc files,
168like images or sound files, add them to \l{qt_add_qml_module}'s \c RESOURCES argument.
169You can find the Module's resources under \c{:/qt/qml/MyQmlLibraryModule/}.
170
171\section1 Replace directory imports with QML module imports
172
173Replace directory imports with QML module imports. For example,
174\badcode
175import "content" // contains SomeType.qml
176// becomes
177import MyQmlModule // contains SomeType.qml
178
179SomeType {
180 ...
181}
182\endcode
183
184Note that files inside a QML module automatically import their own QML module. You can remove the
185self-imports.
186
187\sa {Changes to Qt QML}, {Modern QML modules}
188*/