diff options
Diffstat (limited to 'src/qml/doc/src/qtqml-tool-qmltc.qdoc')
-rw-r--r-- | src/qml/doc/src/qtqml-tool-qmltc.qdoc | 275 |
1 files changed, 0 insertions, 275 deletions
diff --git a/src/qml/doc/src/qtqml-tool-qmltc.qdoc b/src/qml/doc/src/qtqml-tool-qmltc.qdoc deleted file mode 100644 index a9e9256926..0000000000 --- a/src/qml/doc/src/qtqml-tool-qmltc.qdoc +++ /dev/null @@ -1,275 +0,0 @@ -// Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! -\page qtqml-tool-qmltc.html -\title QML Type Compiler -\brief A tool to compile QML types to C++ ahead of time. -\keyword qmltc - -The QML Type Compiler, \c qmltc, is a tool shipped with Qt to translate QML -types into C++ types that are \e{ahead-of-time} compiled as part of the user -code. Using qmltc can lead to better run-time performance due to more -optimization opportunities available to the compiler compared to a -QQmlComponent-based object creation. The qmltc is part of the Qt Quick Compiler -toolchain. - -By design, qmltc outputs user-facing code. That code is supposed to be utilized -by the C++ application directly, otherwise you won't see any benefit. This -generated code essentially replaces QQmlComponent and its APIs to create objects -from QML documents. You can find more information under \l{Using qmltc in a QML -application} and \l{Generated Output Basics}. - -In order to enable qmltc: - -\list - \li Create a \l{qt_add_qml_module}{proper QML module} for your application. - - \li Invoke qmltc, for example, through the \l{qmltc-cmake}{CMake API}. - - \li \c{#include} the generated header file(s) in the application source - code. - - \li Instantiate an object of the generated type. -\endlist - -In this workflow qmltc usually runs during the build process. Thus, when qmltc -rejects a QML document (whether due to errors or warnings, or because of -constructs qmltc doesn't yet support), the build process will fail. This is -similar to how you receive qmllint errors when you enable the automatic -generation of linting targets during \l{qt_add_qml_module}{QML module creation} -and then attempt to "build" them to run the qmllint. - -\warning qmltc is currently in a Tech Preview stage and might not compile an -arbitrary QML program (see \l{Known Limitations} for more details). When qmltc -fails, nothing is generated as your application cannot sensibly use the qmltc -output. If your program contains errors (or unsolvable warnings), they should be -fixed to enable the compilation. The general rule is to adhere to the best -practices and follow \l{qmllint} advice. - -\section2 Using qmltc in a QML application - -From the build system perspective, adding qmltc compilation is not much -different from adding qml cache generation. Naively, the build process could be -described as: - -\image qmltc-compilation-scheme.png - -While the real compilation process is much trickier, this diagram captures the -core components that qmltc uses: the QML files themselves and qmldir with -qmltypes information. Simpler applications typically have rather primitive -qmldir yet, in general, qmldir could be complex, providing essential, nicely -packed type information that qmltc relies on to perform correct QML-to-C++ -translation. - -Nevertheless, adding an extra build step is not enough in qmltc case. The -application code must also be modified to use qmltc-generated classes instead of -QQmlComponent or its higher-level alternatives. - -\section3 Compiling QML code with qmltc - -Qt, starting from Qt 6, uses CMake to build its various components. User -projects can - and are encouraged to - also use CMake to build their components -using Qt. Adding out-of-the-box qmltc compilation support to your project would -require a CMake-driven build flow as well since this flow is centered around -proper QML modules and their infrastructure. - -The easy way to add qmltc compilation is by using the dedicated -\l{qmltc-cmake}{CMake API} as part of a QML module creation for the application. -Consider a simple application directory structure: - -\badcode -. -├── CMakeLists.txt -├── myspecialtype.h // C++ type exposed to QML -├── myspecialtype.cpp -├── myApp.qml // main QML page -├── MyButton.qml // custom UI button -├── MySlider.qml // custom UI slider -└── main.cpp // main C++ application file -\endcode - -Then the CMake code would usually look similar to the following: - -\snippet qmltc/CMakeLists.txt qmltc-app-name -\codeline -\snippet qmltc/CMakeLists.txt qmltc-qml-files -\codeline -\snippet qmltc/CMakeLists.txt qmltc-add-qml-module -\codeline -\snippet qmltc/CMakeLists.txt qmltc-compile-to-cpp - -\section3 Using the Generated C++ - -Unlike in the case of QQmlComponent instantiation, the output of qmltc, being -C++ code, is used directly by the application. Generally, constructing a new -object in C++ is equivalent to creating a new object through -QQmlComponent::create(). Once created, the object could be manipulated from C++ -or, for example, combined with QQuickWindow to be drawn on screen. Given a -\c{myApp.qml} file, the application code (in both cases) would typically look -like this: - -\if defined(onlinedocs) - \tab {generated-c++}{tab-qqmlcomponent}{Using QQmlComponent}{checked} - \tab {generated-c++}{tab-qmltc}{Using qmltc-generated class}{} - \tabcontent {tab-qqmlcomponent} -\else - \section4 Using QQmlComponent -\endif -\snippet qmltc/tst_qmltc_examples.cpp qqmlcomponent-include -\codeline -\snippet qmltc/tst_qmltc_examples.cpp qqmlcomponent-app-code-0 -\codeline -\snippet qmltc/tst_qmltc_examples.cpp qqmlcomponent-app-code-1 -\codeline -\snippet qmltc/tst_qmltc_examples.cpp qqmlcomponent-app-code-2 -\codeline -\snippet qmltc/tst_qmltc_examples.cpp qmltc-app-exec -\if defined(onlinedocs) - \endtabcontent - \tabcontent {tab-qmltc} -\else - \section4 Using qmltc-generated class -\endif -\snippet qmltc/tst_qmltc_examples.cpp qmltc-include -\codeline -\snippet qmltc/tst_qmltc_examples.cpp qmltc-app-code -\codeline -\snippet qmltc/tst_qmltc_examples.cpp qmltc-app-exec -\if defined(onlinedocs) - \endtabcontent -\endif - -\section2 QML engine - -The generated code uses QQmlEngine to interact with dynamic parts of a QML -document - mainly the JavaScript code. For this to work, no special arrangements -are needed. Any QQmlEngine instance passed to the constructor of a -qmltc-generated class object should work correctly as does -\c{QQmlComponent(engine)}. This also means that you can use -\l{QQmlEngine}{QQmlEngine methods} that affect QML behavior. However, there are -caveats. Unlike QQmlComponent-based object creation, qmltc itself \e{does not} -rely on QQmlEngine when compiling the code to C++. For instance, -\c{QQmlEngine::addImportPath("/foo/bar/")} - normally resulting in an additional -import path to scan for - would be completely ignored by the ahead-of-time qmltc -procedure. - -\note To add import paths to the qmltc compilation, consider using a relevant -argument of the \l{qmltc-cmake}{CMake command} instead. - -Generally, you can think of it this way: QQmlEngine involves the application -process to run, while qmltc does not as it operates \e{before} your application -is even compiled. Since qmltc makes no attempt to introspect your application's -C++ source code, there is no way for it to know about certain kinds of QML -manipulations you, as a user, do. Instead of using QQmlEngine and related -run-time routines to expose types to QML, adding import paths, etc. you are, -practically, required to create \l{qt_add_qml_module}{well-behaving QML modules} -and use \l{Defining QML Types from C++}{declarative QML type registration}. - -\warning Despite qmltc working closely with QQmlEngine and creating C++ code, -the generated classes cannot be further exposed to QML and used through -QQmlComponent. - -\section2 Generated Output Basics - -\c qmltc aims to be compatible with the existing QML execution model. This -implies that the generated code is roughly equivalent to the internal -QQmlComponent setup logic and thus you should be able to understand your QML -type's behavior, semantics and API the same way you do currently - by visually -inspecting the corresponding QML document. - -However, the generated code is still somewhat confusing, especially given that -your application should use the qmltc output on the C++ side directly. There are -two parts of the generated code: CMake build files structure and the generated -C++ format. The former is covered in the \l{qmltc-cmake}{CMake API of qmltc} and -the latter is covered here. - -Consider a simple HelloWorld type, that has a \c hello property, a function to -print that property, and a signal emitted when the object of that type is -created: - -\snippet qmltc/special/HelloWorld.qml qmltc-hello-world-qml - -When providing a C++ alternative of this QML type, the C++ class would need a -\l{Overview - QML and C++ Integration}{QML-specific meta-object system macro}, -Q_PROPERTY decoration for the \c hello property, \c{Q_INVOKABLE} C++ printing -function and a regular Qt signal definition. Similarly, qmltc would translate -the given HelloWorld type into roughly the following: - -\snippet qmltc/special/HelloWorld.qml.cpp qmltc-hello-world-generated - -Even though specific details of the generated type could differ, the universal -aspects remain. For instance: - -\list - \li QML types within a document are translated into C++ types, according to - the compiler-visible information. - \li Properties are translated into C++ properties with Q_PROPERTY - declarations. - \li JavaScript functions become \c{Q_INVOKABLE} C++ functions. - \li QML signals are transformed into C++ Qt signals. - \li QML enumerations are converted into C++ enumerations with \c{Q_ENUM} - declarations. -\endlist - -\note \c qmltc does not guarantee that the generated C++ stays API-, source- or -binary-compatible between releases. - -An additional detail is the way \c qmltc generates class names. A class name for -a given QML type is automatically deduced from the QML document defining that -type: the QML file name without extensions (up to and excluding the first \c{.}, -also known as the base name) becomes a class name. The file name case is -preserved. Thus, \c{HelloWorld.qml} would result in a \c{class HelloWorld} and -\c{helloWoRlD.qml} in a \c{class helloWoRlD}. Following the QML convention, if a -QML document file name starts with a lower-case letter, the generated C++ class -is assumed to be anonymous and marked with \l{QML_ANONYMOUS}. - -For now, although the generated code is ready to be used from the C++ -application side, you should generally limit calls to the generated APIs. -Instead, prefer implementing the application logic in QML/JavaScript and -hand-written C++ types exposed to QML, using the qmltc-created classes for -simple object instantiation. While generated C++ gives you direct (and usually -faster) access to QML-defined elements of the type, understanding such code -could be a challenge. - -\section2 Known Limitations - -Despite covering many common QML features, qmltc is still in the early stage of -development with many things yet to be supported. To name a few: - -\list - \li Translation APIs (qsTr() and similar methods) - - \li Inline components - - \li Imported QML modules that consist of QML-defined types (such as - \c{QtQuick.Controls}). At present, you can reliably use \c{QtQml} and - \c{QtQuick} modules as well as any other QML module that \b{only} contains - C++ classes exposed to QML - - \li Singleton QML types -\endlist - -On top of this, there are some more fundamental peculiarities to consider: - -\list - \li Qt's QML modules usually rely on C++ libraries to do the heavy lifting. - Often enough, these libraries do not provide public C++ API (since their - primary usage is through QML). For the users of qmltc, this means that their - apps need to link against private Qt libraries. - - \li Due to the nature of qmltc code generation, QML plugins are unusable for - compilation purposes. Instead, QML modules - that use a plugin - have to - ensure that the plugin data is accessible at compile time. Such QML modules - would then have \e optional plugins. In most cases, the compile-time - information can be provided through a header file (with C++ declarations) - and linkable library (with C++ definitions). The user code is responsible - (usually through CMake) for including a path to the header file and linking - against the QML module library. -\endlist - -Given the tech preview status of the compiler, you might also encounter bugs in -qmltc, in the generated code, or some other related part. We encourage you to -\l{https://bugreports.qt.io/}{submit a bug report} in this case. - -*/ |