Open AdrianEddy opened 3 years ago
Hi,
to the best of my knowledge, Qt5's qmlcachegen
generates some kind of QML bytecode in *.qmlc
format, no intermediate cpp files needed, and it's not a native compiled binary anyway.
With that being said, we could technically extend qrc!()
macro to invoke qmlcachegen
on the fly, and include resulting bytecode with or in place of original QML components — similar to what AUTO_RCC
and AUTO_MOC
do in CMake.
Can you share your tell more about the app you are building that requires pre-compiled QML, and what would be your workflow without Rust, i.e. in pure Qt/CMake?
Hmm, when creating a simple QtQuick project in Qt Creator and enabling Qt Quick Compiler, the build step includes calling qmlcachegen.exe
and it produces a cpp file for each .qml file and a qmlcache_loader.cpp
file. They are later compiled by C++ compiler and included at link stage. I attach simple project (run qmake
and make
there), but the full output is like this:
``` Microsoft (R) Program Maintenance Utility Version 14.29.30038.1 Copyright (C) Microsoft Corporation. All rights reserved. "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30037\bin\HostX64\x64\nmake.exe" -f Makefile.Release Microsoft (R) Program Maintenance Utility Version 14.29.30038.1 Copyright (C) Microsoft Corporation. All rights reserved. D:\Programy\Qt\6.1.1\msvc2019_64\bin\qmlcachegen.exe --resource=D:/test/test/qml.qrc -o release\main_qml.cpp main.qml D:\Programy\Qt\6.1.1\msvc2019_64\bin\qmlcachegen.exe --resource-file-mapping="D:/test/test/qml.qrc=D:/test/test/qml_qmlcache.qrc" -o release\qmlcache_loader.cpp qml.qrc D:\Programy\Qt\6.1.1\msvc2019_64\bin\rcc.exe -name qml_qmlcache qml_qmlcache.qrc -o release\qrc_qml_qmlcache.cpp cl -c -nologo -Zc:wchar_t -FS -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -permissive- -Zc:__cplusplus -Zc:externConstexpr -O2 -MD -std:c++17 -utf-8 -W3 -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 -wd4577 -wd4467 -EHsc -DUNICODE -D_UNICODE -DWIN32 -D_ENABLE_EXTENDED_ALIGNED_STORAGE -DWIN64 -DNDEBUG -DQT_NO_DEBUG -DQT_QUICK_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_QMLMODELS_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -I. -I..\..\Programy\Qt\6.1.1\msvc2019_64\include -I..\..\Programy\Qt\6.1.1\msvc2019_64\include\QtQuick -I..\..\Programy\Qt\6.1.1\msvc2019_64\include\QtOpenGL -I..\..\Programy\Qt\6.1.1\msvc2019_64\include\QtGui -I..\..\Programy\Qt\6.1.1\msvc2019_64\include\QtQmlModels -I..\..\Programy\Qt\6.1.1\msvc2019_64\include\QtQml -I..\..\Programy\Qt\6.1.1\msvc2019_64\include\QtNetwork -I..\..\Programy\Qt\6.1.1\msvc2019_64\include\QtCore -Irelease -I/include -I..\..\Programy\Qt\6.1.1\msvc2019_64\mkspecs\win32-msvc -Forelease\ @C:\Users\Eddy\AppData\Local\Temp\nm17DE.tmp main.cpp cl -c -nologo -Zc:wchar_t -FS -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -permissive- -Zc:__cplusplus -Zc:externConstexpr -O2 -MD -std:c++17 -utf-8 -W3 -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 -wd4577 -wd4467 -EHsc -DUNICODE -D_UNICODE -DWIN32 -D_ENABLE_EXTENDED_ALIGNED_STORAGE -DWIN64 -DNDEBUG -DQT_NO_DEBUG -DQT_QUICK_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_QMLMODELS_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -I. -I..\..\Programy\Qt\6.1.1\msvc2019_64\include -I..\..\Programy\Qt\6.1.1\msvc2019_64\include\QtQuick -I..\..\Programy\Qt\6.1.1\msvc2019_64\include\QtOpenGL -I..\..\Programy\Qt\6.1.1\msvc2019_64\include\QtGui -I..\..\Programy\Qt\6.1.1\msvc2019_64\include\QtQmlModels -I..\..\Programy\Qt\6.1.1\msvc2019_64\include\QtQml -I..\..\Programy\Qt\6.1.1\msvc2019_64\include\QtNetwork -I..\..\Programy\Qt\6.1.1\msvc2019_64\include\QtCore -Irelease -I/include -I..\..\Programy\Qt\6.1.1\msvc2019_64\mkspecs\win32-msvc -Forelease\ @C:\Users\Eddy\AppData\Local\Temp\nm1C06.tmp main_qml.cpp qmlcache_loader.cpp qrc_qml_qmlcache.cpp Generating Code... link /NOLOGO /DYNAMICBASE /NXCOMPAT /OPT:REF /OPT:ICF /INCREMENTAL:NO /SUBSYSTEM:WINDOWS "/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" /MANIFEST:embed /OUT:release\test.exe @C:\Users\Eddy\AppData\Local\Temp\nm2500.tmp ```
Ah, Qt6. That's totally different thing. Haven't tried yet. Gotta take a look. Hang on.
Ah, Qt6. That's totally different thing. Haven't tried yet. Gotta take a look. Hang on.
Qt 5.12 and 5.15 seem to do the same:
``` Microsoft (R) Program Maintenance Utility Version 14.29.30038.1 Copyright (C) Microsoft Corporation. All rights reserved. "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30037\bin\HostX64\x64\nmake.exe" -f Makefile.Release Microsoft (R) Program Maintenance Utility Version 14.29.30038.1 Copyright (C) Microsoft Corporation. All rights reserved. D:\Programy\Qt\5.12.11\msvc2017_64\bin\qmlcachegen.exe --resource=D:/test/test/qml.qrc -o release\main_qml.cpp main.qml D:\Programy\Qt\5.12.11\msvc2017_64\bin\qmlcachegen.exe --resource-file-mapping=D:/test/test/qml.qrc -o release\qmlcache_loader.cpp qml.qrc cl -c -nologo -Zc:wchar_t -FS -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -O2 -MD -W3 -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 -wd4577 -wd4467 -EHsc -DUNICODE -D_UNICODE -DWIN32 -D_ENABLE_EXTENDED_ALIGNED_STORAGE -DWIN64 -DQT_NO_DEBUG -DQT_QUICK_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DNDEBUG -I. -I..\..\Programy\Qt\5.12.11\msvc2017_64\include -I..\..\Programy\Qt\5.12.11\msvc2017_64\include\QtQuick -I..\..\Programy\Qt\5.12.11\msvc2017_64\include\QtGui -I..\..\Programy\Qt\5.12.11\msvc2017_64\include\QtANGLE -I..\..\Programy\Qt\5.12.11\msvc2017_64\include\QtQml -I..\..\Programy\Qt\5.12.11\msvc2017_64\include\QtNetwork -I..\..\Programy\Qt\5.12.11\msvc2017_64\include\QtCore -Irelease -I/include -I..\..\Programy\Qt\5.12.11\msvc2017_64\mkspecs\win32-msvc -Forelease\ @C:\Users\Eddy\AppData\Local\Temp\nm6CC6.tmp main.cpp cl -c -nologo -Zc:wchar_t -FS -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -O2 -MD -W3 -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 -wd4577 -wd4467 -EHsc -DUNICODE -D_UNICODE -DWIN32 -D_ENABLE_EXTENDED_ALIGNED_STORAGE -DWIN64 -DQT_NO_DEBUG -DQT_QUICK_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DNDEBUG -I. -I..\..\Programy\Qt\5.12.11\msvc2017_64\include -I..\..\Programy\Qt\5.12.11\msvc2017_64\include\QtQuick -I..\..\Programy\Qt\5.12.11\msvc2017_64\include\QtGui -I..\..\Programy\Qt\5.12.11\msvc2017_64\include\QtANGLE -I..\..\Programy\Qt\5.12.11\msvc2017_64\include\QtQml -I..\..\Programy\Qt\5.12.11\msvc2017_64\include\QtNetwork -I..\..\Programy\Qt\5.12.11\msvc2017_64\include\QtCore -Irelease -I/include -I..\..\Programy\Qt\5.12.11\msvc2017_64\mkspecs\win32-msvc -Forelease\ @C:\Users\Eddy\AppData\Local\Temp\nm6E9B.tmp main_qml.cpp qmlcache_loader.cpp Generating Code... link /NOLOGO /DYNAMICBASE /NXCOMPAT /INCREMENTAL:NO /SUBSYSTEM:WINDOWS "/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" /MANIFEST:embed /OUT:release\test.exe @C:\Users\Eddy\AppData\Local\Temp\nm7071.tmp ```
Mystery solved: qmlcachegen
has more than one operating mode. Which one will be chosen depends on output file name.
https://code.woboq.org/qt5/qtdeclarative/tools/qmlcachegen/qmlcachegen.cpp.html#437
enum Output {
GenerateCpp,
GenerateCacheFile,
GenerateLoader
} target = GenerateCacheFile;
if (outputFileName.endsWith(QLatin1String(".cpp"))) {
target = GenerateCpp;
if (outputFileName.endsWith(QLatin1String("qmlcache_loader.cpp")))
target = GenerateLoader;
}
EDIT
Woboq code browser is a little bit out of date (Generated on 2019-Aug-01 from project qtdeclarative revision v5.13.0-452-g4bac72aa13). Now, in Qt6, there's a fourth option:
if (target == GenerateLoader && parser.isSet(resourceNameOption))
target = GenerateLoaderStandAlone;
For reference, here's how I implemented it in my app: https://github.com/gyroflow/gyroflow/blob/1f685e483f8abc27e9f0ec5f177563ae1407430f/build.rs#L10-L63
It would be nice to have a way to enable Qt Quick Compiler when using qml files embedded in qrc.
Looks like it just requires to invoke
qmlcachegen
and compile the resulting cpp file