Correct way to make QML modules Qt 6.5-6.9
-
Hello, I have a small sketch of the structure of the project that I started writing on Qt 6.9, and I decided to try using Cmake tools instead of the old approach with resources and qmldir.
So my project structure:
App
├── CMakeLists.txt
├── src/
│ ├── core/
│ │ ├── models/
│ │ ├── controllers/
│ │ ├── services/
│ │ └── utils/
│ ├── UI/
│ │ ├── Assets/
│ │ |----|── Asset.qml
│ │ |----|── CmakeLists.txt
│ │ ├── Pages/
│ │ | ----|── MainPage.qml
│ │ | ----|── CmakeLists.txt
│ │ ├── Components/
│ │ | ----|── MButton.qml
│ │ | ----|── CmakeLists.txt
│ │ ├── CmakeLists.txt
│ └── main.cpp
├── resources/
└── tests/I want Assets Pages and Components to be separate modules and connected via import.
So in Components I do
qt_add_qml_module(Components URI UI.Components VERSION 1.0 QML_FILES MButton.qml MImageButton.qml MSlider.qml )
as with all other modules.
And I get errors and warnings
if I link statically, I have a lot of dirt in the project tree.
What I do wrong? It is possible to link Module without qt_add_library(lib STATIC)?
Here is my project for the full picture:
https://github.com/Deymoss/MoneyTogether/tree/masterIn summary, what is the correct and working way to use QML modules? And starting from which version does it work?
-
Hi
you show us partly how you build the exported library, but you don't show how you import it.
I suggest you watch this video and follow the pattern described.
By the way, since Qt 6.5 there's a new QQmlApplicationEngine::loadFromModule method that can be used instead of load.However, all those subprojects in the Assets and Components directories are possibly generated by yourself.
Did you make multiple calls to qt_add_executable or qt_add_library in a single CMakeLists.txt ? -
Hi
you show us partly how you build the exported library, but you don't show how you import it.
I suggest you watch this video and follow the pattern described.
By the way, since Qt 6.5 there's a new QQmlApplicationEngine::loadFromModule method that can be used instead of load.However, all those subprojects in the Assets and Components directories are possibly generated by yourself.
Did you make multiple calls to qt_add_executable or qt_add_library in a single CMakeLists.txt ?@CassD
I have attached a repository with the full code, but now I will duplicate the approach here.So i do in app/modules/UI/Components/CMakeLists.txt
qt_add_qml_module(Components URI UI.Components VERSION 1.0 QML_FILES MButton.qml MImageButton.qml MSlider.qml )
next in app/modules/UI/CMakeLists.txt
add_subdirectory(Components)
next in app/CMakeLists.txt
cmake_minimum_required(VERSION 3.16) project(MoneyTogether VERSION 0.1 LANGUAGES CXX) set(CMAKE_AUTOMOC ON) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(QT_QML_GENERATE_QMLLS_INI OFF) find_package(Qt6 REQUIRED COMPONENTS Gui Quick REQUIRED) qt_standard_project_setup(REQUIRES 6.9) qt_add_executable(appMoneyTogether main.cpp ) qt_add_qml_module(appMoneyTogether URI MoneyTogether VERSION 1.0 QML_FILES Main.qml ) add_subdirectory(modules/UI) add_subdirectory(modules/Core) add_subdirectory(modules/Models) add_subdirectory(modules/Data) add_subdirectory(modules/Auth) add_subdirectory(modules/Sync) # set(QML_IMPORT_PATH "${CMAKE_SOURCE_DIR}/qml") # Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1. # If you are developing for iOS or macOS you should consider setting an # explicit, fixed bundle identifier manually though. set_target_properties(appMoneyTogether PROPERTIES # MACOSX_BUNDLE_GUI_IDENTIFIER com.example.appMoneyTogether MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} MACOSX_BUNDLE TRUE WIN32_EXECUTABLE TRUE QT_QML_IMPORT_PATH "${QML_IMPORT_PATH}" ) target_link_libraries(appMoneyTogether PRIVATE Qt6::Gui Qt6::Quick Assets Components Pages ) install(TARGETS appMoneyTogether BUNDLE DESTINATION . LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} )
So, this fits in with what they say in the guide, but it doesn't work, maybe some more steps are needed, maybe in main.cpp Should I specify something?
In this video Lukas show that it is possible without qt_add_library, so I came here with the question of how to make it work. -
I build all my qmlmodules into a single folder
set(QML_IMPORT_PATH ${CMAKE_BINARY_DIR}/qml CACHE STRING "" FORCE )
With this your folder would look like this:
qml
├── UI.Components
├── UI.otherModuleAnd the import in your qml files would be "import UI.Components"
-
I build all my qmlmodules into a single folder
set(QML_IMPORT_PATH ${CMAKE_BINARY_DIR}/qml CACHE STRING "" FORCE )
With this your folder would look like this:
qml
├── UI.Components
├── UI.otherModuleAnd the import in your qml files would be "import UI.Components"
-
@Redman
So it turns out that the working approach is to put everything in one folder and split the files into modules, then it will look divided in the project tree?@Deymos Sorry, I forgot a piece of code.
set(QML_IMPORT_PATH ${CMAKE_BINARY_DIR}/qml CACHE STRING "" FORCE ) set(QT_QML_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/qml)
With this code you build all your modules into the qml folder. And you tell the qml engine where to look for modules if you do import statements in your qml files.
If you then link against your module like you do in your repo you should be able to "import UI.Components"
@Deymos said in Correct way to make QML modules Qt 6.5-6.9:
then it will look divided in the project tree?
You can leave your structure the way it is.
-
@Deymos Sorry, I forgot a piece of code.
set(QML_IMPORT_PATH ${CMAKE_BINARY_DIR}/qml CACHE STRING "" FORCE ) set(QT_QML_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/qml)
With this code you build all your modules into the qml folder. And you tell the qml engine where to look for modules if you do import statements in your qml files.
If you then link against your module like you do in your repo you should be able to "import UI.Components"
@Deymos said in Correct way to make QML modules Qt 6.5-6.9:
then it will look divided in the project tree?
You can leave your structure the way it is.
@Redman
wow, seems to this approach is working
but I have a little trouble, I got this
But file is present and in correct path
after cleaning the build, the error from Qt creator disappeared, but the "module "UI.Pages" is not installed" remained at startup.
on work pc i have only Qt 6.2.0, i will also try on 6.9.0 6 hours later
-
@Redman
wow, seems to this approach is working
but I have a little trouble, I got this
But file is present and in correct path
after cleaning the build, the error from Qt creator disappeared, but the "module "UI.Pages" is not installed" remained at startup.
on work pc i have only Qt 6.2.0, i will also try on 6.9.0 6 hours later
-
@Redman
wow, seems to this approach is working
but I have a little trouble, I got this
But file is present and in correct path
after cleaning the build, the error from Qt creator disappeared, but the "module "UI.Pages" is not installed" remained at startup.
on work pc i have only Qt 6.2.0, i will also try on 6.9.0 6 hours later
-
@Deymos said in Correct way to make QML modules Qt 6.5-6.9:
but the "module "UI.Pages" is not installed" remained at startup.
What does that mean?
some incredibly strange behavior, I added QML_IMPORT_PATH, my HomePage from the module UI.Pages was created and displayed a message to me, but the module UI.Components is still nowhere to be seen, although there are no special rules for it.
It issues these warnings.
Before I deleted the build folder, the warnings were displayed only for the UI.Assets, maybe the QML language server is buggy, I do not know.
But in the end, HomePage creates, but Components(MButton) does not see.
If i removed MButton and starting with only HomePage (from UI.Pages):
Very strange, they just the same modules, with the same connection way.
I'm updated repo, if you want to look or test https://github.com/Deymoss/MoneyTogether
-
@Redman
So I commented this line and deleted the build folder
But unfortunately nothing is changed, probably this approach of moduling is not working and I need an add_library(STATIC) on each module, but I really don't want to, because there will be a mountain of garbage in the project tree.
Or something missing -
@Redman
So I commented this line and deleted the build folder
But unfortunately nothing is changed, probably this approach of moduling is not working and I need an add_library(STATIC) on each module, but I really don't want to, because there will be a mountain of garbage in the project tree.
Or something missing -
-
@Redman
Yeah, I've seen this option.
Thank you very much for your help, I will keep an eye on updates, and as soon as there is a way to make everything working in Qt, I will write in this thread and mark it as solved.@Deymos said in Correct way to make QML modules Qt 6.5-6.9:
HomePage creates, but Components(MButton) does not see.
To make it work:
- Order matters. You must set
QT_QML_OUTPUT_DIRECTORY
before your very first call toqt_add_qml_module()
- This ensures that the setting is applied to every QML module in your project.
- Set QT_QML_OUTPUT_DIRECTORY to
${CMAKE_BINARY_DIR}
, not${CMAKE_BINARY_DIR}/qml
.- This puts the QML module folders at the same level as your executable, so the executable can automatically find the modules and plugins at runtime (when you run it directly from your build dir)
- I tested this on Windows and Ubuntu
- To use MButton, you need
import UI.Components
and notimport UI.Assets
Note: There is no point linking your executable to
Assets
,Components
, andPages
libraries because your executable does not use any C++ symbols from those libraries. Instead, you need your executable to find the QML plugins at runtime.@Deymos said in Correct way to make QML modules Qt 6.5-6.9:
on work pc i have only Qt 6.2.0
Qt 6.2 is far too old. QML modules have changed a lot since then.
@Deymos said in Correct way to make QML modules Qt 6.5-6.9:
I added QML_IMPORT_PATH
QML_IMPORT_PATH
is used by Qt Creator's old code model. It is not used by the new QML Language Server (qmlls). Likewise,QT_QML_GENERATE_QMLLS_INI
is only used by qmlls and not the old code model.By default, you'll be using qmlls if:
- You're running the latest Qt Creator, AND
- You're using Qt 6.8 or newer for your project
- Order matters. You must set
-
@Deymos said in Correct way to make QML modules Qt 6.5-6.9:
HomePage creates, but Components(MButton) does not see.
To make it work:
- Order matters. You must set
QT_QML_OUTPUT_DIRECTORY
before your very first call toqt_add_qml_module()
- This ensures that the setting is applied to every QML module in your project.
- Set QT_QML_OUTPUT_DIRECTORY to
${CMAKE_BINARY_DIR}
, not${CMAKE_BINARY_DIR}/qml
.- This puts the QML module folders at the same level as your executable, so the executable can automatically find the modules and plugins at runtime (when you run it directly from your build dir)
- I tested this on Windows and Ubuntu
- To use MButton, you need
import UI.Components
and notimport UI.Assets
Note: There is no point linking your executable to
Assets
,Components
, andPages
libraries because your executable does not use any C++ symbols from those libraries. Instead, you need your executable to find the QML plugins at runtime.@Deymos said in Correct way to make QML modules Qt 6.5-6.9:
on work pc i have only Qt 6.2.0
Qt 6.2 is far too old. QML modules have changed a lot since then.
@Deymos said in Correct way to make QML modules Qt 6.5-6.9:
I added QML_IMPORT_PATH
QML_IMPORT_PATH
is used by Qt Creator's old code model. It is not used by the new QML Language Server (qmlls). Likewise,QT_QML_GENERATE_QMLLS_INI
is only used by qmlls and not the old code model.By default, you'll be using qmlls if:
- You're running the latest Qt Creator, AND
- You're using Qt 6.8 or newer for your project
@JKSH
Thanks for answer, QT_QML_OUTPUT_DIRECTORY on top of qt_add_qml_module() really helped and now everything is working fine!@JKSH said in Correct way to make QML modules Qt 6.5-6.9:
To use MButton, you need import UI.Components and not import UI.Assets
my bad, my eyes were busy with the warnings and I didn't notice :)
@JKSH said in Correct way to make QML modules Qt 6.5-6.9:
QML_IMPORT_PATH is used by Qt Creator's old code model. It is not used by the new QML Language Server (qmlls). Likewise, QT_QML_GENERATE_QMLLS_INI is only used by qmlls and not the old code model.
By default, you'll be using qmlls if:
You're running the latest Qt Creator, AND You're using Qt 6.8 or newer for your project
So can i use modules with "old" approach if I have Qt 6.5 and 16 creator? What is the difference when using without QMLLS on Qt 6.5? or is it the same, just don't write QT_QML_GENERATE_QMLLS_INI and add QML_IMPORT_PATH?
@JKSH said in Correct way to make QML modules Qt 6.5-6.9:
Note: There is no point linking your executable to Assets, Components, and Pages libraries because your executable does not use any C++ symbols from those libraries
and if I use C++ in this module, as I understand it, I will just need to link these modules, and the behavior will remain the same?
- Order matters. You must set
-
@JKSH
Thanks for answer, QT_QML_OUTPUT_DIRECTORY on top of qt_add_qml_module() really helped and now everything is working fine!@JKSH said in Correct way to make QML modules Qt 6.5-6.9:
To use MButton, you need import UI.Components and not import UI.Assets
my bad, my eyes were busy with the warnings and I didn't notice :)
@JKSH said in Correct way to make QML modules Qt 6.5-6.9:
QML_IMPORT_PATH is used by Qt Creator's old code model. It is not used by the new QML Language Server (qmlls). Likewise, QT_QML_GENERATE_QMLLS_INI is only used by qmlls and not the old code model.
By default, you'll be using qmlls if:
You're running the latest Qt Creator, AND You're using Qt 6.8 or newer for your project
So can i use modules with "old" approach if I have Qt 6.5 and 16 creator? What is the difference when using without QMLLS on Qt 6.5? or is it the same, just don't write QT_QML_GENERATE_QMLLS_INI and add QML_IMPORT_PATH?
@JKSH said in Correct way to make QML modules Qt 6.5-6.9:
Note: There is no point linking your executable to Assets, Components, and Pages libraries because your executable does not use any C++ symbols from those libraries
and if I use C++ in this module, as I understand it, I will just need to link these modules, and the behavior will remain the same?
You're welcome! Glad to hear that it's now working for you.
@Deymos said in Correct way to make QML modules Qt 6.5-6.9:
So can i use modules with "old" approach if I have Qt 6.5 and 16 creator?
Yes. You could also do one of:
- Force the "old" code model for all projects by turning off qmlls completely
- Force qmlls to be used even if you're using an older kit
https://doc.qt.io/qtcreator/creator-how-to-use-qml-language-server.html
What is the difference when using without QMLLS on Qt 6.5? or is it the same, just don't write QT_QML_GENERATE_QMLLS_INI and add QML_IMPORT_PATH?
Yes, that's right. Although it's harmless to have both
QT_QML_GENERATE_QMLLS_INI
andQML_IMPORT_PATH
in your project (the main problem is that it's a bit "noisy" and might confuse a reader).The "old" code model is part of the Qt Creator IDE; qmlls is part of the Qt libraries. So qmlls gets updated with each Qt release. You can choose to use the version of qmlls that comes with your kit, or you can choose to use the newest available qmlls on your machine.
-
You're welcome! Glad to hear that it's now working for you.
@Deymos said in Correct way to make QML modules Qt 6.5-6.9:
So can i use modules with "old" approach if I have Qt 6.5 and 16 creator?
Yes. You could also do one of:
- Force the "old" code model for all projects by turning off qmlls completely
- Force qmlls to be used even if you're using an older kit
https://doc.qt.io/qtcreator/creator-how-to-use-qml-language-server.html
What is the difference when using without QMLLS on Qt 6.5? or is it the same, just don't write QT_QML_GENERATE_QMLLS_INI and add QML_IMPORT_PATH?
Yes, that's right. Although it's harmless to have both
QT_QML_GENERATE_QMLLS_INI
andQML_IMPORT_PATH
in your project (the main problem is that it's a bit "noisy" and might confuse a reader).The "old" code model is part of the Qt Creator IDE; qmlls is part of the Qt libraries. So qmlls gets updated with each Qt release. You can choose to use the version of qmlls that comes with your kit, or you can choose to use the newest available qmlls on your machine.
-