Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-110075

Linker failure when using Q_IMPORT_QML_PLUGIN() on external static QML plugin

    XMLWordPrintable

Details

    • Linux/X11, Windows

    Description

      Attached are 2 projects which consist of a simple static QML plugin and a simple application that uses that plugin:

      └── MyModule
          ├── CMakeLists.txt
          ├── MyItem.qml
      └── MyApp
          ├── CMakeLists.txt
          ├── main.cpp
          ├── main.qml
      

       

      Relevant parts of <ROOT>/MyModule/CMakeLists.txt:

      project(MyModule)
      
      if (NOT DEFINED MY_QML_DIR)
          set(MY_QML_DIR ${CMAKE_SOURCE_DIR}/../qml)
      endif()
      set(QT_QML_OUTPUT_DIRECTORY ${MY_QML_DIR})
      
      qt_add_qml_module(MyModule
          URI MyModule
          VERSION 1.0
          STATIC
          QML_FILES MyItem.qml
      )
      

       

      Relevant parts of <ROOT>/MyApp/CMakeLists.txt:

      project(MyApp)
      
      if (NOT DEFINED MY_QML_DIR)
          set(MY_QML_DIR ${CMAKE_SOURCE_DIR}/../qml)
      endif()
      
      qt_add_executable(appMyApp
          main.cpp
      )
      qt_add_qml_module(appMyApp
          URI MyApp
          VERSION 1.0
          IMPORTS MyModule
          IMPORT_PATH ${MY_QML_DIR}
          QML_FILES main.qml 
      )
      
      target_link_directories(appMyApp PRIVATE ${MY_QML_DIR}/MyModule)
      target_link_libraries(appMyApp
          PRIVATE Qt6::Quick MyModuleplugin)
      

       

      Relevant parts of <ROOT>/MyApp/main.cpp:

      int main(int argc, char *argv[])
      {
          Q_IMPORT_QML_PLUGIN(MyModulePlugin);
          // ...
      }
      

       

      Steps to reproduce

      1. Build <ROOT>/MyModule/CMakeLists.txt as a standalone project
      2. Build <ROOT>/MyApp/CMakeLists.txt as a standalone project (using the same Kit as above)

       

      Outcome

      Step #1 builds fine, but Step #2 fails:

      /usr/bin/ld: <ROOT>/qml/MyModule/libMyModuleplugin.a(MyModuleplugin_MyModulePlugin.cpp.o): in function `qt_plugin_instance_MyModulePlugin()':
      MyModuleplugin_MyModulePlugin.cpp:(.text+0xc2): undefined reference to `qml_register_types_MyModule()'
      /usr/bin/ld: <ROOT>/qml/MyModule/libMyModuleplugin.a(MyModuleplugin_MyModulePlugin.cpp.o): in function `QtPrivate::QMetaTypeForType<MyModulePlugin>::getDefaultCtr()::{lambda(QtPrivate::QMetaTypeInterface const*, void*)#1}::_FUN(QtPrivate::QMetaTypeInterface const*, void*)':
      MyModuleplugin_MyModulePlugin.cpp:(.text._ZZN9QtPrivate16QMetaTypeForTypeI14MyModulePluginE13getDefaultCtrEvENUlPKNS_18QMetaTypeInterfaceEPvE_4_FUNES5_S6_[_ZZN9QtPrivate16QMetaTypeForTypeI14MyModulePluginE13getDefaultCtrEvENUlPKNS_18QMetaTypeInterfaceEPvE_4_FUNES5_S6_]+0x2e): undefined reference to `qml_register_types_MyModule()'
      

      ...even though nm -C libMyModuleplugin.a shows that qml_register_types_MyModule() exists.

       

      Workaround

      Merge both projects into a single CMake tree by adding <ROOT>/CMakeLists.txt (which is already provided in the attachment):

      cmake_minimum_required(VERSION 3.16)
      project(MyMergedProject)
      set(MY_QML_DIR ${CMAKE_SOURCE_DIR}/qml)
      
      add_subdirectory(MyModule)
      add_subdirectory(MyApp)
      

      This lets us successfully build and run the application.

       

      Notes

      • When merging into a single project tree, _Q_IMPORT_QML_PLUGIN()_ is not necessary
      • When building MyApp as standalone project, building/linking completes without errors if _Q_IMPORT_QML_PLUGIN()_ is removed. However, this means the QML resources become unavailable at runtime.

      Attachments

        Issue Links

          Activity

            People

              qtbuildsystem Qt Build System Team
              skoh-qt Sze Howe Koh
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: