Is QML translated into native code at the compilation time or is it interpreted at runtime almost the way JavaScript is ran in a web browser?
QML has a deep JavaScript integration, and allows signal handlers and methods to be defined in JavaScript. Another core feature of QML is the ability to specify and enforce relationships between object properties using property bindings, which are also defined using JavaScript.
The QML Native Code Components give you full native access, out of the box! They allow working with all native iOS and Android platform APIs directly from QML and provide a bridge between Qt Quick and the underlying native platform.
The QML Type Compiler, (qmltc) compiles QML types to C++ classes. These C++ classes are then added to your application and can be instantiated from other C++ code. This way you can avoid much of the overhead of using QQmlComponent to create instances of your QML types.
QML (Qt Modeling Language) is a user interface markup language. It is a declarative language (similar to CSS and JSON) for designing user interface–centric applications. Inline JavaScript code handles imperative aspects.
AFAIK, there seem to be no straight and detailed explanation in the Qt documentation, but some Qt hackers try to explain it:
QML is compiled to an optimized bytecode-like stream and the JavaScript expressions pass through an optimized evaluator for simple expressions.
There also is related QTBUG task QtQuick startup time needs to be improved; cache compiled QML between runs
My understanding is that QML status hasn't been settled completely and engineers don't declare it fixed, so they have freedom to improve it in future.
ATM, it best advice is to mix C++ with QML, having all application logic in C++ and presentation in QML, but ideally divided into smaller QML files, not in a single large QML file.
With Qt 5.3 and an enterprise license, there is actually a way to have it precompiled.
https://doc.qt.io/QtQuickCompiler/
This is useful for iOS where Apple doesn't allow JIT code generation.
I just had the same question, and here is what the situation looks now, a few years down the road:
The most advanced technique in Qt 5 is using ahead-of-time QML compilation. This uses QuickCompiler, a tool that was "Introduced in Qt 5.3 for commercial licensees, both commercial and open source in Qt 5.11" (source). From an older documentation of QtQuickCompiler it becomes more clear what it actually does:
[Without QtQuickCompiler the] popular Just-in-time (JIT) compilation technique is used to generate machine code on the fly [from QML], which speeds up the execution of JavaScript and QML binding expressions.
Unfortunately this approach has some disadvantages: […] some platform versions such as iOS or Windows RT do not permit the dynamic generation of machine code. […]
Compiled Qt Quick [via QtQuickCompiler] is an elegant solution to these problems: .qml files as well as accompanying .js files can be translated into intermediate C++ source code. After compilation with a traditional compiler, the code is linked into the application binary.
This ahead-of-time compilation with QtQuickCompiler produces the same bytecode that just-in-time (JIT) compilation would otherwise produce at runtime from QML. QtQuickCompiler indeed produces "intermediate C++ source code", but that is simply bytecode in C++ data structures, to be embedded into the resulting C++ executable. I tested it; to see it for yourself, you just have to build a Qt Quick project with QtQuickCompiler enabled, and then open file {filename}_qml.cpp
in your build directory, which has been generated for your {filename}.qml
. It will look like this:
// /{filename}.qml
namespace QmlCacheGeneratedCode {
namespace _0x5f__main_qml {
extern const unsigned char qmlData alignas(16) [] = {
0x71,0x76,0x34,0x63,0x64,0x61,0x74,0x61,
0x20,0x0,0x0,0x0,0x4,0xc,0x5,0x0,
// … many many more lines …
0x40,0x0,0x40,0x1,0x40,0x0,0xf0,0x1,
0x0,0x0,0x0,0x0
};
}
}
So in Qt 5, QML is neither translated into native [C++] code at compilation time, nor interpreted at runtime. It is instead compiled ahead-of-time to bytecode. This bytecode will then be run in a small virtual machine for JavaScript, similar to what is done with Java bytecode in the JVM. A virtual machine is always needed because compiling machine code from a weakly typed language like QML / JavaScript is not possible.
When neither QtQuickCompiler nor JIT compilation with caching is available, "QML provides an interpreter to allow for the full use of QML, but it comes at the expense of a longer execution time." (source)
It is planned that the future release of Qt 6 will indeed include the translation of QML into native C++ code, which is then compiled just as any other C++ code:
Support compiling QML to efficient C++ and native code. With strong typing and simpler lookup rules we can convert QML to efficient C++ and native code, significantly increasing runtime performance. (source)
I have to say, that sounds great :)
There's a big difference between compiled languages and interpreted languages. A QML document is interpreted by the QML runtime. In a sense, you can say that it is executed like JavaScript.
The QML runtime includes a QML engine, JavaScript engine, and mechanism to bind to the Qt Framework.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With