Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Emscripten fails with undefined synbols in QPlatformIntegration



  • Hi,

    I have made a pretty awesome Qt demo in WebAssembly. It worked perfectly in my old Qt5.12 setup, but I have now updated to the 5.13 branch (and switched to emscripten version 1.38.31) and now I get an issue when i build my application.

    Yes, I could probably switch back and work around this. But I would really like to know the inner works of Qt for WebAssembly and some of the problems that may lie ahead (Before suggesting adding Qt to our Toolbox).

    Problem
    It seems some QPlatformIntegration symbols are not found (specifically screenAdded and destroyScreen )
    I believe these platform specific stuff should reside in qt5/qtbase/plugins/platforms/libqwasm.a (Is this correct??)
    As this lib is already on the commandline, who is then to blame? Should the symbols not be looked for in the first place or should they be part of libqwasm? Or am I missing something else?

    Any suggestions are more than welcome. Thanks!

    The failing command:

    em++ -s WASM=1 -s FULL_ES2=1 -s USE_WEBGL2=1 -s NO_EXIT_RUNTIME=0 -s ERROR_ON_UNDEFINED_SYMBOLS=1	 --bind -s "BINARYEN_TRAP_MODE='clamp'" -O3 -s ALLOW_MEMORY_GROWTH=1 -s USE_FREETYPE=1 /Area51/wasm/qt5/qtbase/lib/libqtlibpng.a -o target/floorview.js generated_files/main.o generated_files/mainwindow.o generated_files/flooreditor.o generated_files/floorview.o generated_files/rack.o generated_files/floorview.js_plugin_import.o generated_files/qrc_images.o generated_files/moc_mainwindow.o generated_files/moc_flooreditor.o generated_files/moc_floorview.o   /Area51/wasm/qt5/qtbase/plugins/platforms/libqwasm.a /Area51/wasm/qt5/qtbase/lib/libQt5EventDispatcherSupport.a /Area51/wasm/qt5/qtbase/lib/libQt5FontDatabaseSupport.a -s USE_FREETYPE=1 /Area51/wasm/qt5/qtbase/lib/libQt5EglSupport.a /Area51/wasm/qt5/qtbase/plugins/imageformats/libqgif.a /Area51/wasm/qt5/qtbase/plugins/imageformats/libqicns.a /Area51/wasm/qt5/qtbase/plugins/imageformats/libqico.a /Area51/wasm/qt5/qtbase/plugins/imageformats/libqjpeg.a /Area51/wasm/qt5/qtbase/plugins/imageformats/libqtga.a /Area51/wasm/qt5/qtbase/plugins/imageformats/libqtiff.a /Area51/wasm/qt5/qtbase/plugins/imageformats/libqwbmp.a /Area51/wasm/qt5/qtbase/plugins/imageformats/libqwebp.a /Area51/wasm/qt5/qtbase/plugins/egldeviceintegrations/libqeglfs-emu-integration.a -L/Area51/wasm/qt5/qtbase/lib -lQt5EglFSDeviceIntegration -lQt5EventDispatcherSupport -lQt5ServiceSupport -lQt5ThemeSupport -lQt5FontDatabaseSupport /Area51/wasm/qt5/qtbase/lib/libqtfreetype.a -lQt5FbSupport -lQt5EglSupport -lQt5PlatformCompositorSupport -lQt5Gui -lQt5DeviceDiscoverySupport -lQt5Core /Area51/wasm/qt5/qtbase/lib/libQt5OpenGL.a /Area51/wasm/qt5/qtbase/lib/libQt5Widgets.a /Area51/wasm/qt5/qtbase/lib/libQt5Gui.a /Area51/wasm/qt5/qtbase/lib/libqtlibpng.a /Area51/wasm/qt5/qtbase/lib/libqtharfbuzz.a /Area51/wasm/qt5/qtbase/lib/libQt5Core.a /Area51/wasm/qt5/qtbase/lib/libqtpcre2.a
    emcc: warning: cannot represent a NaN literal '0x7fd81ce3cff0' with custom bit pattern in NaN-canonicalizing JS engines (e.g. Firefox and Safari) without erasing bits!
      in   ret double 0x7FF4000000000000 in _ZL7qt_snanv.9577()
    error: undefined symbol: _ZN20QPlatformIntegration11screenAddedEP15QPlatformScreenb
    warning: To disable errors for undefined symbols use `-s ERROR_ON_UNDEFINED_SYMBOLS=0`
    error: undefined symbol: _ZN20QPlatformIntegration13destroyScreenEP15QPlatformScreen
    Error: Aborting compilation due to previous errors
    shared:ERROR: '/Area51/emsdk/node/8.9.1_64bit/bin/node /Area51/emsdk/emscripten/1.38.31/src/compiler.js /tmp/tmpIaB7hU.txt /Area51/emsdk/emscripten/1.38.31/src/embind/emval.js /Area51/emsdk/emscripten/1.38.31/src/embind/embind.js /Area51/emsdk/emscripten/1.38.31/src/library_pthread_stub.js' failed (1)
    

  • Lifetime Qt Champion

    Hi,

    Maybe @lorn-potter may know something about this.



  • @SGaist and @lorn-potter I changed the emscripten version to 1.38.27 as that is listed as "the known good one" for Qt5.13.

    I rebuild Qt.

    configure command used:

    ./configure -opensource -confirm-license -xplatform wasm-emscripten -nomake examples -prefix $PWD/qtbase
    

    Still the same problem when building my project.



  • Minor progress. I can now make the build work if I manually edit one of the files generated by QMake.

    So qmake creates this [project-name].js_plugin_import.cpp and in my case the contents of that files is:

    #include <QtPlugin>
    Q_IMPORT_PLUGIN(QWasmIntegrationPlugin)
    Q_IMPORT_PLUGIN(QGifPlugin)
    Q_IMPORT_PLUGIN(QICNSPlugin)
    Q_IMPORT_PLUGIN(QICOPlugin)
    Q_IMPORT_PLUGIN(QJpegPlugin)
    Q_IMPORT_PLUGIN(QTgaPlugin)
    Q_IMPORT_PLUGIN(QTiffPlugin)
    Q_IMPORT_PLUGIN(QWbmpPlugin)
    Q_IMPORT_PLUGIN(QWebpPlugin)
    Q_IMPORT_PLUGIN(QEglFSEmulatorIntegrationPlugin)
    

    I have no idea why it contains all these plugins as that is not something I have specified directly. When I comment out the last one ( QEglFSEmulatorIntegrationPlugin) my problem disappears and my application still works. My logic was that I already had the QWasmIntegrationPlugin and the error was about integration ... :-)

    So the working version:

    #include <QtPlugin>
    Q_IMPORT_PLUGIN(QWasmIntegrationPlugin)
    Q_IMPORT_PLUGIN(QGifPlugin)
    Q_IMPORT_PLUGIN(QICNSPlugin)
    Q_IMPORT_PLUGIN(QICOPlugin)
    Q_IMPORT_PLUGIN(QJpegPlugin)
    Q_IMPORT_PLUGIN(QTgaPlugin)
    Q_IMPORT_PLUGIN(QTiffPlugin)
    Q_IMPORT_PLUGIN(QWbmpPlugin)
    Q_IMPORT_PLUGIN(QWebpPlugin)
    //Q_IMPORT_PLUGIN(QEglFSEmulatorIntegrationPlugin)
    

    But editing a generated file is really not a solution.

    So my question is now:

    • Is it a problem to have two integration plugins?
    • Should I remove the last plugin and if so how should I go about doing so?


  • @lwallent said in Emscripten fails with undefined synbols in QPlatformIntegration:

    QEglFSEmulatorIntegrationPlugin

    It seems for whatever reason, that the QEglFSEmulatorIntegrationPlugin might be installed in your Qt wasm installation.

    Which OS is this on? And how did you install Qt for WebAssembly?

    You could go into, for instance if you installed the binaries from Qt:
    Qt/5.13.0/wasm_32/plugins, find and delete the QEglFSEmulatorIntegrationPlugin if it exists.
    If it does not exist, I am not sure how that line got there, but it should not be there.



  • @lorn-potter I am on OsX and I have Qt cloned from the github repo (and checked out branch 5.13)

    As I did not really know which submodules I neded, I checked out the whole shebang using ./init-repository -f. Could this course problems?

    I cannot quite recognise the plugins path you specify. If I do a find . -type d -name wasm in the Qt directory, I get the following:

    ./qtbase/mkspecs/features/wasm
    ./qtbase/src/plugins/platforms/wasm
    ./qtbase/src/gui/platform/wasm
    ./qtbase/src/corelib/platform/wasm
    ./qtbase/src/3rdparty/wasm
    ./qtwebengine/src/3rdparty/chromium/v8/tools/wasm
    ./qtwebengine/src/3rdparty/chromium/v8/src/wasm
    ./qtwebengine/src/3rdparty/chromium/third_party/ink/build/wasm
    

    If I do a grep for the plugin name (QEglFSEmulatorIntegrationPlugin) it self - in the Qt5 folder I get (besides a lot of test folders):

    ./qtbase/lib/cmake/Qt5Gui/Qt5Gui_QEglFSEmulatorIntegrationPlugin.cmake:add_library(Qt5::QEglFSEmulatorIntegrationPlugin MODULE IMPORTED)
    ./qtbase/lib/cmake/Qt5Gui/Qt5Gui_QEglFSEmulatorIntegrationPlugin.cmake:_populate_Gui_plugin_properties(QEglFSEmulatorIntegrationPlugin RELEASE "egldeviceintegrations/libqeglfs-emu-integration.a")
    ./qtbase/lib/cmake/Qt5Gui/Qt5Gui_QEglFSEmulatorIntegrationPlugin.cmake:list(APPEND Qt5Gui_PLUGINS Qt5::QEglFSEmulatorIntegrationPlugin)
    ./qtbase/mkspecs/modules/qt_plugin_qeglfs-emu-integration.pri:QT_PLUGIN.qeglfs-emu-integration.CLASS_NAME = QEglFSEmulatorIntegrationPlugin
    ./qtbase/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemumain.cpp:class QEglFSEmulatorIntegrationPlugin : public QEglFSDeviceIntegrationPlugin
    ./qtbase/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/eglfs_emu.pro:PLUGIN_CLASS_NAME = QEglFSEmulatorIntegrationPlugin
    Binary file ./qtbase/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/.obj/qeglfsemumain.o matches
    ./qtbase/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/Makefile:	-$(DEL_FILE) *.html *.js *.wasm /Users/lasse/Development/wasm/qt5/qtbase/lib/cmake/Qt5Gui/Qt5Gui_QEglFSEmulatorIntegrationPlugin.cmake ../../../../../../plugins/egldeviceintegrations/libqeglfs-emu-integration.prl
    ./qtbase/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/.moc/qeglfsemumain.moc:struct qt_meta_stringdata_QEglFSEmulatorIntegrationPlugin_t {
    ./qtbase/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/.moc/qeglfsemumain.moc:    qptrdiff(offsetof(qt_meta_stringdata_QEglFSEmulatorIntegrationPlugin_t, stringdata0) + ofs \
    ./qtbase/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/.moc/qeglfsemumain.moc:static const qt_meta_stringdata_QEglFSEmulatorIntegrationPlugin_t qt_meta_stringdata_QEglFSEmulatorIntegrationPlugin = {
    ./qtbase/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/.moc/qeglfsemumain.moc:QT_MOC_LITERAL(0, 0, 31) // "QEglFSEmulatorIntegrationPlugin"
    ./qtbase/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/.moc/qeglfsemumain.moc:    "QEglFSEmulatorIntegrationPlugin"
    ./qtbase/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/.moc/qeglfsemumain.moc:static const uint qt_meta_data_QEglFSEmulatorIntegrationPlugin[] = {
    ./qtbase/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/.moc/qeglfsemumain.moc:void QEglFSEmulatorIntegrationPlugin::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
    ./qtbase/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/.moc/qeglfsemumain.moc:QT_INIT_METAOBJECT const QMetaObject QEglFSEmulatorIntegrationPlugin::staticMetaObject = { {
    ./qtbase/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/.moc/qeglfsemumain.moc:    qt_meta_stringdata_QEglFSEmulatorIntegrationPlugin.data,
    ./qtbase/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/.moc/qeglfsemumain.moc:    qt_meta_data_QEglFSEmulatorIntegrationPlugin,
    ./qtbase/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/.moc/qeglfsemumain.moc:const QMetaObject *QEglFSEmulatorIntegrationPlugin::metaObject() const
    ./qtbase/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/.moc/qeglfsemumain.moc:void *QEglFSEmulatorIntegrationPlugin::qt_metacast(const char *_clname)
    ./qtbase/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/.moc/qeglfsemumain.moc:    if (!strcmp(_clname, qt_meta_stringdata_QEglFSEmulatorIntegrationPlugin.stringdata0))
    ./qtbase/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/.moc/qeglfsemumain.moc:int QEglFSEmulatorIntegrationPlugin::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
    ./qtbase/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/.moc/qeglfsemumain.moc:QT_MOC_EXPORT_PLUGIN(QEglFSEmulatorIntegrationPlugin, QEglFSEmulatorIntegrationPlugin)
    Binary file ./qttools/src/qtdiag/.obj/qtdiag.js_plugin_import.o matches
    ./qttools/src/qtdiag/qtdiag.js_plugin_import.cpp:Q_IMPORT_PLUGIN(QEglFSEmulatorIntegrationPlugin)
    

    Not sure what is the right thing to do here?


Log in to reply