Commit f1e97b19 authored by Craig Scott's avatar Craig Scott
Browse files

QML CMake API review meeting 3 agenda

parent 1129de59
# QML CMake API review meeting agenda
## Should we preserve existing plugin target names or change them to use the default?
There are certain repos that specify a custom PLUGIN_TARGET with the previously added plugin name, instead of using the automatically generated name. Is there a good reason to keep those?
At least for the Qt build itself, we don't need to set the PLUGIN_TARGET names, the auto-generated name should be ok.
The advantage of removing, is the code won't be cargo culted into other projects.
The advantage of keeping, is user projects can see the explicit target name for deployment purposes, but that's a bit far-fetched.
Just a proposal
```cmake
qt_add_qml_module(Qml
# When not specified, the default target name will be QmlPlugin, so backing lib name + Plugin suffix
PLUGIN_TARGET QmlPlugin,
# The output name of the plugin when not specified should be lower case target name + snake case _plugin suffix.
FICTIONAL_PLUGIN_OUTPUT_NAME qml_plugin -> # libqml_plugin.so
```
**Decision:** TBD
## Discussion about the behavior of target creation by default
* `qt_add_qml_module()` calls `qt_add_qml_plugin()` by default. Plugin target will be created if it doesn't already exist.
* `qt_add_qml_module()` + `NO_CREATE_PLUGIN_TARGET` means -> won't call `qt_add_qml_plugin()`, user project will do it.
You still need to specify `PLUGIN_TARGET`, even though the project will create it later.
All three of the following examples work:
```cmake
# CASE 1: Pre-create plugin target, NO_CREATE_PLUGIN_TARGET not needed since auto-detected
qt_add_qml_plugin(FooPlugin)
qt_add_qml_module(Foo PLUGIN_TARGET FooPlugin)
```
```cmake
# CASE 2: Pre-create plugin target, NO_CREATE_PLUGIN_TARGET explicitly given but not necessary
qt_add_qml_plugin(FooPlugin)
qt_add_qml_module(Foo NO_CREATE_PLUGIN_TARGET PLUGIN_TARGET FooPlugin)
```
```cmake
# CASE 3: Prevent plugin target creation, do it later after the call
qt_add_qml_module(Foo NO_CREATE_PLUGIN_TARGET PLUGIN_TARGET FooPlugin)
qt_add_qml_plugin(FooPlugin)
```
NOTE: `qt_internal_add_qml_module()` currently relies on being able to pre-create the plugin target before it calls `qt_add_qml_module()` (case 1). It may be possible to modify it to match case 2 if we wanted to eliminate case 1. User projects should be able to do at least cases 2 and 3.
* Are we happy with supporting all of the above cases?
* Should we add an explicit `NO_CREATE_TARGET` option too, which must be provided if passing in an existing target for the backing target?
* Would have to think about the case where the plugin and backing target are merged.
**Decisions:** TBD
## Should we rename NO_GENERATE_SOURCE to NO_GENERATE_PLUGIN_SOURCE in qt_add_qml_plugin()?
JIRA: [QTBUG-95090](https://bugreports.qt.io/browse/QTBUG-95090)
This would make the keyword the same as the associated keyword in `qt_add_qml_module()`. Potential counter-argument: the `qt_add_qml_plugin()` command name is already about plugins.
**Decision:** TBD
## Should we always enable AUTOMOC for qml modules?
I think we tacitly agreed the answer is yes, but have we fully thought through the consequences of this? Type registration does have code paths for AUTOMOC being off, so it might not be
**Decision:** TBD
## What should be the default output directory of qml modules? How does it impact tooling or running an app?
We previously decided to change the default to `${CMAKE_BINARY_DIR}/qml`. We then discarded the `/qml` part, but this made everything get dumped into the top of the build tree. We then decided to put the default back to `${CMAKE_CURRENT_BINARY_DIR}`, but keep the support for a `QT_QML_OUTPUT_DIRECTORY` variable to specify the base below which QML modules are output based on their `TARGET_PATH`.
* To be confirmed: will qml hot-reloading work? What are the requirements?
Consider an app whose executable is a QML module, and it uses a couple of other QML modules. The main app's URI might be `BasicApp`, while QML module it uses might be `TimeExample` and `OtherStuff`. The `main.qml` will likely want to do `import TimeExample`, but this won't work at run time using just the resources without adding something to the import path.
*Source directory structure:*
```
+-- main.qml
+-- Foo.qml
+-- TimeExample
| +-- Clock.qml
+-- OtherStuff
+-- blah.qml
```
Build directory structure should be the same as the source directory structure, but will also have `qmldir` files. But the resources will be different because they are based on a QML module's TARGET_PATH, which is based on the module's URI. Since we made the app a QML module as well, it has a URI and therefore it has a non-empty TARGET_PATH:
*Resources structure:*
```
+-- BasicApp
| +-- main.qml
| +-- Foo.qml
| +-- qmldir
+-- TimeExample
| +-- Clock.qml
| +-- qmldir
+-- OtherStuff
+-- blah.qml
+-- qmldir
```
Running `qmllint` on any of the `BasicApp` qml files will find `TimeExample` via the implicit import path. But let's say that `TimeExample` does an `import OtherStuff` and we run `qmllint` on `TimeExample`'s qml files. In order for `qmllint` to find `OtherStuff`, we would likely need to add the root of the above directory tree to `qmllint`'s import path. If `QT_QML_OUTPUT_DIRECTORY` is set, then that is easy because that variable is precisely the path we would need to add. If that variable is not set, we would have to walk up the directory tree from `TimeExample` and add the base dir, then assume all other QML modules will also be under that base location.
* Do we require projects to follow this rigid directory structure?
* It still won't work if some QML modules come from other projects. When installed, things might all be under a coherent directory structure, but at build time, some QML modules might be in separate places.
* Projects sometimes have their own constraints that require them to structure things differently (e.g. conformance to rigid coding standards that dictate directory structures). These constraints are not always reasonable, but the developers might not have any freedom to change them.
* Maybe we need to give projects a way to add import paths to be used only during the build and only for tooling like `qmllint`, `qmlcachegen`, etc.
* The `IMPORT_PATH` option to `qt_add_qml_module()` is for run time, so it can't be used for this.
* Could tooling like `qmllint`, `qmlcachegen`, etc. be taught to walk up the `TARGET_PATH` of the QML module they are processing and search for imports below its base point automatically? Or do they do this already? It still wouldn't help for QML modules that are in separate parts of the file system (e.g. provided by third party packages).
NOTE: May merge the discussion of the next topic into this one too.
**Decisions:** TBD
## What's our expectation on linking to a backing library without a plugin, and ensure that it works?
This absorbs/replaces the following two questions from the first API review meeting:
* Do we want to support static-backing-lib-but-shared-plugin use case?
* How do we support multiple qml modules in a single executable?
Possible scenario is an executable that links to multiple static backing libs (i.e. uses multiple QML modules). Runtime loading is better, assuming we can solve the problem of the linker discarding global initializers. Unclear what the role of shared plugins is in this scenario, needs clarification.
Build dir layout shouldn't matter, the use case involves an executable that links directly to all QML modules' backing libraries and only that executable is installed (if the backing libraries are shared libraries, those would need to be installed too). Nothing else gets installed, everything should be loaded from resources and compiled-in stuff at run time. Assume that none of the QML modules are singletons and all plugins are optional for this particular scenario.
It's a valid use case, but it might need some additional fixes in the qml engine (to be confirmed). Projects would have to add the resource import path under which all its QML modules can be found (e.g. `qrc:/`).
Open questions:
* Is there anything we still need to do to support this use case?
* Do we want to document how to set up this scenario for 6.2, or should we delay doing that until we have a robust solution to the problem of preventing the linker from discarding global constructors that register our modules, etc. (affects both shared and static libraries and plugins)? Projects would still be free to try it for 6.2 if they want to handle the linker issues their own way.
* Would a lot of our problems in the previous topic go away if we said executables cannot be QML modules? Executables can link to static libraries as QML modules and not really lose any functionality. The executables would then typically just be a simple `main.qml`, added as an ordinary resource.
**Decisions:** TBD
## Do we want to restrict `qt_target_qml_sources()` to require that the target given to it must be a QML module?
Certain simple use cases can use an ordinary target that isn't a QML module and still run `qmllint` and `qmlcachegen` successfully. QML team has raised concerns that this won't work in general for all but simple cases.
* If we add this constraint, do we still support a non-QML executable with a simple `main.qml` that uses other QML modules?
* If so, how would we expect them to add that `main.qml` file to the app resources?
* `qt_add_resources()` would work, but seems to go against our "use the provided `qt_target_qml_sources()` command for adding qml files" mantra.
**Decision:** TBD
## We now run qmllint on the files in the source directory. There won't be any qmldir files there. Is that a problem?
`qmllint` gets a set of `.qrc` files passed to it. One of those will contain the `qmldir` of the module/target. But `qmldir` files of any other QML modules won't be found without adding an import path for the build directory. But then you will get a mix of source and build directory files for any imported QML modules. If any warning messages need to refer to those other-QML-module files, you're back to potentially seeing the build directory copies mentioned instead of the source directory files.
**Decision:** TBD
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment