CMake: a QML module that uses QtMultimedia (or other Qt non-core module)
-
Building on an M1 Mac machine ?
-
How did you install Qt ?
Because from the looks of it you might be mixing x86_64 and arm64 libraries.
-
I use Qt's 'Maintenance Tool' installer.
Just in case there had been a problem, I've just uninstalled and reinstalled Qt 6.2.3 with Qt Multimedia. And I deleted the build folder before rebuilding. But I still get this problem.
Any idea how to get around it?
-
Can you post the full compile output somewhere?
-
Are you building from the command line ?
If so, you should activate an x86_64 shell and only then do your build.
-
Sorry, been away on holiday. But I have now created a minimal project and tested it on Mac (M1) and Windows 10, both using Qt Creator 7.0.0 with Qt 6.2.3. I get equivalent errors.
In case it's of relevance, within my code I have to put
#include <QtMultimedia/QAudioSink>
rather than#include <QAudioSink>
. Perhaps it's not just the object linking that's missing, but the include directories too??Below are:
- CMake output on Mac M1
- Build output on Mac M1
- CMake output on Windows 10
- Build output on Windows 10
- CMakeList.txt
- Synthesizer.h
- Synthesizer.cpp
- main.cpp
- main.qml
CMake output on Mac M1
Running /Users/me/Qt/Tools/CMake/CMake.app/Contents/bin/cmake -S /Users/me/Code/minimalSynthesizer -B /Users/me/Code/build-minimalSynthesizer-Qt_6_2_3_for_macOS-Debug '-DCMAKE_GENERATOR:STRING=Unix Makefiles' -DCMAKE_BUILD_TYPE:STRING=Debug '-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=/Users/me/Qt/Qt Creator.app/Contents/Resources/package-manager/auto-setup.cmake' -DQT_QMAKE_EXECUTABLE:STRING=/Users/me/Qt/6.2.3/macos/bin/qmake -DCMAKE_PREFIX_PATH:STRING=/Users/me/Qt/6.2.3/macos -DCMAKE_C_COMPILER:STRING=/usr/bin/gcc -DCMAKE_CXX_COMPILER:STRING=/usr/bin/clang++ in /Users/me/Code/build-minimalSynthesizer-Qt_6_2_3_for_macOS-Debug. -- The CXX compiler identification is AppleClang 13.0.0.13000029 -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Check for working CXX compiler: /usr/bin/clang++ - skipped -- Detecting CXX compile features -- Detecting CXX compile features - done -- Looking for C++ include pthread.h -- Looking for C++ include pthread.h - found -- Performing Test CMAKE_HAVE_LIBC_PTHREAD -- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success -- Found Threads: TRUE -- Performing Test HAVE_STDATOMIC -- Performing Test HAVE_STDATOMIC - Success -- Found WrapAtomic: TRUE -- Found OpenGL: /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/OpenGL.framework -- Found WrapOpenGL: TRUE -- Configuring done -- Generating done -- Build files have been written to: /Users/me/Code/build-minimalSynthesizer-Qt_6_2_3_for_macOS-Debug Elapsed time: 00:01.
Build output on Mac M1 (includes link errors)
14:12:57: Running steps for project minimalSynthesizer... 14:12:57: Persisting CMake state... 14:12:58: Starting: "/Users/me/Qt/Tools/CMake/CMake.app/Contents/bin/cmake" --build /Users/me/Code/build-minimalSynthesizer-Qt_6_2_3_for_macOS-Debug --target appSynth [ 3%] Built target appSynth_tooling [ 7%] Automatic MOC for target Synth [ 7%] Built target Synth_autogen [ 10%] Running AUTOMOC file extraction for target Synth [ 10%] Built target Synth_automoc_json_extraction [ 14%] Running moc --collect-json for target Synth [ 17%] Automatic QML type registration for target Synth [ 21%] Running rcc for resource qmake_Synth Consolidate compiler generated dependencies of target Synth [ 25%] Building CXX object CMakeFiles/Synth.dir/Synth_autogen/mocs_compilation.cpp.o [ 28%] Building CXX object CMakeFiles/Synth.dir/synth_qmltyperegistrations.cpp.o [ 32%] Building CXX object CMakeFiles/Synth.dir/.rcc/qrc_qmake_Synth.cpp.o [ 35%] Building CXX object CMakeFiles/Synth.dir/Synthesizer.cpp.o [ 39%] Linking CXX shared library libSynth.dylib Undefined symbols for architecture arm64: "QAudioSink::stop()", referenced from: Synthesizer::stop() in Synthesizer.cpp.o "QAudioSink::start(QIODevice*)", referenced from: Synthesizer::startPull(QIODevice*) in Synthesizer.cpp.o "QAudioSink::QAudioSink(QAudioFormat const&, QObject*)", referenced from: Synthesizer::startPull(QIODevice*) in Synthesizer.cpp.o ld: symbol(s) not found for architecture arm64 clang: error: linker command failed with exit code 1 (use -v to see invocation) make[3]: *** [libSynth.dylib] Error 1 make[2]: *** [CMakeFiles/Synth.dir/all] Error 2 make[1]: *** [CMakeFiles/appSynth.dir/rule] Error 2 make: *** [appSynth] Error 2 14:13:00: The process "/Users/me/Qt/Tools/CMake/CMake.app/Contents/bin/cmake" exited with code 2. Error while building/deploying project minimalSynthesizer (kit: Qt 6.2.3 for macOS) When executing step "Build" 14:13:00: Elapsed time: 00:02.
CMake output on Windows 10
Logging in and fetching licenses ... Checking for updated license succeeded (3 licenses fetched) Running C:\Qt\Tools\CMake_64\bin\cmake.exe -S C:/Users/me/OneDrive/Documents/Code/OMI-experiments/minimalSynthesizer -B C:/Users/me/OneDrive/Documents/Code/OMI-experiments/build-minimalSynthesizer-Desktop_Qt_6_2_3_MSVC2019_64bit-Debug "-DCMAKE_GENERATOR:STRING=Ninja" "-DCMAKE_BUILD_TYPE:STRING=Debug" "-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=C:/Qt/Tools/QtCreator/share/qtcreator/package-manager/auto-setup.cmake" "-DQT_QMAKE_EXECUTABLE:STRING=C:/Qt/6.2.3/msvc2019_64/bin/qmake.exe" "-DCMAKE_PREFIX_PATH:STRING=C:/Qt/6.2.3/msvc2019_64" "-DCMAKE_C_COMPILER:STRING=C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.30.30705/bin/HostX64/x64/cl.exe" "-DCMAKE_CXX_COMPILER:STRING=C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.30.30705/bin/HostX64/x64/cl.exe" in C:\Users\me\OneDrive\Documents\Code\OMI-experiments\build-minimalSynthesizer-Desktop_Qt_6_2_3_MSVC2019_64bit-Debug. -- The CXX compiler identification is MSVC 19.30.30706.0 -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Check for working CXX compiler: C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.30.30705/bin/HostX64/x64/cl.exe - skipped -- Detecting CXX compile features -- Detecting CXX compile features - done -- Looking for C++ include pthread.h -- Looking for C++ include pthread.h - not found -- Found Threads: TRUE -- Performing Test HAVE_STDATOMIC -- Performing Test HAVE_STDATOMIC - Success -- Found WrapAtomic: TRUE -- Could NOT find WrapVulkanHeaders (missing: Vulkan_INCLUDE_DIR) -- Could NOT find WrapVulkanHeaders (missing: Vulkan_INCLUDE_DIR) -- Configuring done -- Generating done -- Build files have been written to: C:/Users/me/OneDrive/Documents/Code/OMI-experiments/build-minimalSynthesizer-Desktop_Qt_6_2_3_MSVC2019_64bit-Debug Elapsed time: 00:07.
Build output on Windows 10 (includes link errors)
21:02:05: Running steps for project minimalSynthesizer... 21:02:05: Starting: "C:\Qt\Tools\CMake_64\bin\cmake.exe" --build C:/Users/me/OneDrive/Documents/Code/OMI-experiments/build-minimalSynthesizer-Desktop_Qt_6_2_3_MSVC2019_64bit-Debug --target appSynth [1/25 0.9/sec] Automatic MOC for target Synth [2/25 1.8/sec] Running AUTOMOC file extraction for target Synth [3/25 2.6/sec] Running moc --collect-json for target Synth [4/25 1.8/sec] Automatic QML type registration for target Synth [5/25 1.9/sec] Building CXX object CMakeFiles\Synth.dir\.rcc\qrc_qmake_Synth.cpp.obj [6/25 1.5/sec] Building CXX object CMakeFiles\Synth.dir\Synth_autogen\mocs_compilation.cpp.obj [7/25 1.7/sec] Building CXX object CMakeFiles\Synth.dir\Synthesizer.cpp.obj [8/25 1.7/sec] Building CXX object CMakeFiles\Synth.dir\synth_qmltyperegistrations.cpp.obj [9/25 1.2/sec] Linking CXX shared library Synth.dll FAILED: Synth.dll Synth.lib cmd.exe /C "cd . && C:\Qt\Tools\CMake_64\bin\cmake.exe -E vs_link_dll --intdir=CMakeFiles\Synth.dir --rc=C:\PROGRA~2\WI3CF2~1\10\bin\100190~1.0\x64\rc.exe --mt=C:\PROGRA~2\WI3CF2~1\10\bin\100190~1.0\x64\mt.exe --manifests -- C:\PROGRA~1\MICROS~1\2022\COMMUN~1\VC\Tools\MSVC\1430~1.307\bin\Hostx64\x64\link.exe /nologo CMakeFiles\Synth.dir\Synth_autogen\mocs_compilation.cpp.obj CMakeFiles\Synth.dir\synth_qmltyperegistrations.cpp.obj CMakeFiles\Synth.dir\.rcc\qrc_qmake_Synth.cpp.obj CMakeFiles\Synth.dir\Synthesizer.cpp.obj /out:Synth.dll /implib:Synth.lib /pdb:Synth.pdb /dll /version:0.0 /machine:x64 /debug /INCREMENTAL C:\Qt\6.2.3\msvc2019_64\lib\Qt6Qmld.lib C:\Qt\6.2.3\msvc2019_64\lib\Qt6Networkd.lib C:\Qt\6.2.3\msvc2019_64\lib\Qt6Cored.lib mpr.lib userenv.lib ws2_32.lib shell32.lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib && cd ." LINK Pass 1: command "C:\PROGRA~1\MICROS~1\2022\COMMUN~1\VC\Tools\MSVC\1430~1.307\bin\Hostx64\x64\link.exe /nologo CMakeFiles\Synth.dir\Synth_autogen\mocs_compilation.cpp.obj CMakeFiles\Synth.dir\synth_qmltyperegistrations.cpp.obj CMakeFiles\Synth.dir\.rcc\qrc_qmake_Synth.cpp.obj CMakeFiles\Synth.dir\Synthesizer.cpp.obj /out:Synth.dll /implib:Synth.lib /pdb:Synth.pdb /dll /version:0.0 /machine:x64 /debug /INCREMENTAL C:\Qt\6.2.3\msvc2019_64\lib\Qt6Qmld.lib C:\Qt\6.2.3\msvc2019_64\lib\Qt6Networkd.lib C:\Qt\6.2.3\msvc2019_64\lib\Qt6Cored.lib mpr.lib userenv.lib ws2_32.lib shell32.lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /MANIFEST /MANIFESTFILE:CMakeFiles\Synth.dir/intermediate.manifest CMakeFiles\Synth.dir/manifest.res" failed (exit code 1120) with the following output: Creating library Synth.lib and object Synth.exp Synthesizer.cpp.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: __cdecl QAudioSink::QAudioSink(class QAudioFormat const &,class QObject *)" (__imp_??0QAudioSink@@QEAA@AEBVQAudioFormat@@PEAVQObject@@@Z) referenced in function "public: void __cdecl Synthesizer::startPull(class QIODevice *)" (?startPull@Synthesizer@@QEAAXPEAVQIODevice@@@Z) Synthesizer.cpp.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: virtual __cdecl QAudioSink::~QAudioSink(void)" (__imp_??1QAudioSink@@UEAA@XZ) referenced in function "public: virtual void * __cdecl QAudioSink::`scalar deleting destructor'(unsigned int)" (??_GQAudioSink@@UEAAPEAXI@Z) Synthesizer.cpp.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: void __cdecl QAudioSink::start(class QIODevice *)" (__imp_?start@QAudioSink@@QEAAXPEAVQIODevice@@@Z) referenced in function "public: void __cdecl Synthesizer::startPull(class QIODevice *)" (?startPull@Synthesizer@@QEAAXPEAVQIODevice@@@Z) Synthesizer.cpp.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: void __cdecl QAudioSink::stop(void)" (__imp_?stop@QAudioSink@@QEAAXXZ) referenced in function "public: void __cdecl Synthesizer::stop(void)" (?stop@Synthesizer@@QEAAXXZ) Synthesizer.cpp.obj : error LNK2001: unresolved external symbol "public: virtual struct QMetaObject const * __cdecl QAudioSink::metaObject(void)const " (?metaObject@QAudioSink@@UEBAPEBUQMetaObject@@XZ) Synthesizer.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void * __cdecl QAudioSink::qt_metacast(char const *)" (?qt_metacast@QAudioSink@@UEAAPEAXPEBD@Z) Synthesizer.cpp.obj : error LNK2001: unresolved external symbol "public: virtual int __cdecl QAudioSink::qt_metacall(enum QMetaObject::Call,int,void * *)" (?qt_metacall@QAudioSink@@UEAAHW4Call@QMetaObject@@HPEAPEAX@Z) Synth.dll : fatal error LNK1120: 7 unresolved externals ninja: build stopped: subcommand failed. 21:02:13: The process "C:\Qt\Tools\CMake_64\bin\cmake.exe" exited with code 1. Error while building/deploying project minimalSynthesizer (kit: Desktop Qt 6.2.3 MSVC2019 64bit) When executing step "Build" 21:02:13: Elapsed time: 00:08.
CMakeList.txt
cmake_minimum_required(VERSION 3.16) project(minimalSynthesizer VERSION 0.1 LANGUAGES CXX) set(CMAKE_AUTOMOC ON) set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(Qt6 6.2 COMPONENTS Quick Multimedia REQUIRED) qt_add_executable(appSynth main.cpp ) qt_add_qml_module(appSynth URI minimalSynthesizer VERSION 1.0 QML_FILES main.qml ) 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_compile_definitions(appSynth PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>) target_link_libraries(appSynth PRIVATE Qt6::Quick Qt6::Multimedia Synth )
Synthesizer.h
#pragma once #include <QObject> #include <QtMultimedia/QAudioFormat> #include <QtMultimedia/QAudioSink> class Synthesizer : public QObject { Q_OBJECT public: explicit Synthesizer(const QAudioFormat &format, QObject *parent = nullptr); virtual ~Synthesizer(); void startPull(QIODevice *device); void stop(); private: QAudioFormat _audioFormat; QAudioSink *_audioSink; };
Synthesizer.cpp
#include "Synthesizer.h" Synthesizer::Synthesizer(const QAudioFormat &format, QObject *parent) : QObject{parent} , _audioFormat(format) , _audioSink(nullptr) { } Synthesizer::~Synthesizer() { stop(); } void Synthesizer::startPull(QIODevice *device) { stop(); _audioSink = new QAudioSink(_audioFormat); _audioSink->start(device); } void Synthesizer::stop() { if (_audioSink == nullptr) return; _audioSink->stop(); _audioSink->deleteLater(); _audioSink = nullptr; }
main.cpp (default for Qt Quick project)
#include <QGuiApplication> #include <QQmlApplicationEngine> int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQmlApplicationEngine engine; const QUrl url(u"qrc:/minimalSynthesizer/main.qml"_qs); QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [url](QObject *obj, const QUrl &objUrl) { if (!obj && url == objUrl) QCoreApplication::exit(-1); }, Qt::QueuedConnection); engine.load(url); return app.exec(); }
main.qml (default for Qt Quick project)
import QtQuick Window { width: 640 height: 480 visible: true title: qsTr("Hello World") }
-
OK I'm a bit closer, but I don't have a solution.
Within
qt_add_qml_module
, you have to include allSOURCE
classes/functions that are used.For example, if I made my
Synthesizer
class depend on another class,AudioMakers
then the source (AudioMakers.h
&AudioMakers.cpp
) must be in theSOURCE
list and omitting them gives the same errors.If I just include the headers of dependant classes/functions (i.e.
AudioMakers.h
) then I get a different bunch of messages that mean "Hey the definitions are missing for some declarations!"So there must be a way of creating a QML module and letting it know where to find referenced functions without having to include them within
SOURCE
. Any ideas? -
Sorry, I lost track on this one.
What is the status now ?
-
@SGaist Still stuck. And still a blocking issue for my project.
I've worked out that the errors are not platform/CPU specific. They're about dependencies.
Synthesizer
depends on classes/functions not in the QML module. I've created this question about the general case (where the classes/functions it is dependent on are elsewhere within the project) — no responses as yet.And this thread is about the specific case where those dependencies are in a Qt module.
It would be great to get solutions to both questions, if you're able (or can loop in the right person at Qt).
-
@paulmasri said in CMake: a QML module that uses QtMultimedia (or other Qt non-core module):
qt_add_qml_module(Synth
URI Synth
VERSION 1.0
SOURCES
Synthesizer.h Synthesizer.cpp
)Shouldn't that be Synthplugin ?
With an additional:
target_link_libraries(Synthplugin PRIVATE Qt6::Quick Qt6::Multimedia )
?
-
Did you add:
target_link_libraries(Synthplugin PRIVATE Qt6::Quick Qt6::Multimedia )
to you CMakeLists.txt ?
-
@SGaist Looks like we were writing our last messages at the same time. Yes I did try exactly that and it makes no difference.
I note that the documentation for
qt_add_qml_module
has optional keywordsDEPENDENCIES
andIMPORTS
but there are no examples and the descriptions aren't clear about how/whether they could be used for a module like QtMultimedia. -
DEPENDENCIES
is only relevant for resolving dependencies between QML modules at runtime, or for tools like qmllint.
It does not affect linking relationships at all.I suggest you push your current project state to some repository (like github) and share it and the errors you get, because it's not entirely clear what fails at the moment.
For example in your post at https://forum.qt.io/post/711286 you link
Qt6::Multimedia
intoappSynth
rather thanSynth
.To ensure Multimedia symbols are found, you need to link
Qt6::Multimedia
into the target whose sources uses multimedia symbols.Within qt_add_qml_module, you have to include all SOURCE classes/functions that are used.
For example, if I made my Synthesizer class depend on another class, AudioMakers then the source (AudioMakers.h & AudioMakers.cpp) must be in the SOURCE list and omitting them gives the same errors.I'm not sure I understand this statement.
All sources both (.cpp and .h) should indeed be specified as sources. either via qt_add_qml_module'sSOURCES
option or usingtarget_sources
.