Search code examples
qtcmakedependenciesqt6

How to specify dependencies in qt_add_qml_module (CMake for Qt 6.2)


When using qt_add_qml_module to specify a QML module, how do you handle Qt modules that it depends on (e.g. QtMultimedia)?


If I have class Synthesizer that extends QML, but which has no dependencies, the following works fine:

qt_add_qml_module(Synth
    URI Synth
    VERSION 1.0
    SOURCES
        Synthesizer.h Synthesizer.cpp
)

target_include_directories(Synthplugin
     PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
)

target_link_libraries(myapp
    PRIVATE Qt6::Quick
    Synth
)

However if Synthesizer uses QtMultimedia classes, then this is insufficient, and results in errors like:

Undefined symbols for architecture arm64:
  "QAudioSink::start()", referenced from:
      Synthesizer::start() in Synthesizer.cpp.o

Solution

  • I now have a tried and tested approach, based on putting each QML module into its own library.

    First create the library within subfolder Synth:

    qt_add_library(SynthLib STATIC)
    
    qt_add_qml_module(SynthLib
        URI Synth
        VERSION 1.0
        SOURCES
            Synthesizer.h Synthesizer.cpp
    )
    
    target_include_directories(SynthLib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
    
    target_link_libraries(SynthLib
        PUBLIC Qt6::Multimedia
    )
    

    Within the main CMakeLists.txt, make sure the Multimedia package is loaded. Then add the library as a subdirectory. Finally link the library into the application.

    find_package(Qt6 6.2 REQUIRED COMPONENTS Quick Multimedia)
    
    add_subdirectory(Synth)
    
    ...
    
    target_link_libraries(myapp
        PRIVATE
            Qt6::Quick
            SynthLibplugin
    )
    
    

    Notes

    • Because the Synth library links to Qt6::Multimedia and the main app doesn't directly use Qt Multimedia, there's no need for the main app to link to Qt6::Multimedia.
    • If our library had been a standard C++ library, i.e. where qt_add_library() includes the source files and there is no qt_add_qml_module(), then myapp would link to SynthLib. However because we're linking to a QML module, the Qt magic generates a QML plugin and we have to link to that instead, i.e. SynthLibplugin.
    • If Qt Multimedia headers were included only in Synthesizer.cpp, then SynthLib could have a PRIVATE link to Qt6::Multimedia. However if we have included Qt Multimedia headers in the .h (e.g. #include <QtMultimedia/QAudioFormat>) then it has to be a PUBLIC link because the header file may be included in other files, meaning those files need to be able to link to Qt Multimedia. I've shown this latter case above.