The qmltyperegistrar tool will generate a C++ file ..._qmltyperegistrations.cpp like the following:
It relies on something in one of the included headers marking the generated qml_register_types_...() function as an exported symbol. If no header does this, the function will not have global visibility in the final library. When a separate plugin and backing target is used for a qml module, this results in the plugin not being able to access the function and linking fails.
The above code example is a good demonstration of the problem, as it shows one way projects are currently working around this bug. They basically find one of the headers that will be pulled in by the generated XXX_qmltyperegistrations.cpp file and make sure it includes the header that does declare the qml_register_types_...() function as exported. That makes the modified header depend on another header that it technically shouldn't need to (this would cause a warning with tools like IWYU).
Perhaps one solution would be to generate an associated header to go with the generated XXX_qmltyperegistrations.cpp file. The plugin could then include that header and nothing else will likely need to. Alternatively, we could force exporting the function by declaring it for export directly in the generated XXX_qmltyperegistrations.cpp file. Either method would have to account for whether building for a static or shared library, platform/compiler differences, etc.