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

Application with plugin crashes after calling macdeployqt.



  • Hi, Ive made a desktop application, and a plugin for it. I load the plugin this way:

        QPluginLoader pl(dir.absoluteFilePath(fileName));
        BrushInterface *b = qobject_cast<BrushInterface *>( pl.instance());
        if(b != nullptr){
         //Some instructions with the plugin
        }
    

    It works fine, but when i use macdeployqt to be able to deploy the application to other computers, it crashes when loading the plugin.
    The same on windows works perfectly using windeployqt, and on linux using linuxdeployqt and making an appimage. The problem is only present with macdeployqt. Is there any extra steps i must do to use plugin system with mac?

    I don't even know how to get the chrash error on mac.


  • Lifetime Qt Champion

    Hi,

    What version of Qt ?
    What version of macOS ?
    What crash stacktrace do you get ?



  • @SGaist Hi! thanks for the answer and sorry for the late response.

    I'm using Qt 5.13.0
    I'm using MacOS Sierra 10.12.6
    I'm not a Mac user, and i don't really know how to get the stacktrace of a crashing app. I've tried using "sample process" in the Activity Monitor, but it stops writing when the app crash. Is there any other way?

    I must stress that when running the app before using macdeployqt, everything works. But after using macdeployqt, it crashes when loading the plugin.



  • @SGaist Another thing i've just noticed. The app only crash if i open the "*.app", but if i navigate to the Contents/MacOS/myexecutable file from temrinal and run it from there, it works.


  • Lifetime Qt Champion

    You should get a report automatically as macOS generates it for you on application crash.

    If you don't get one it's maybe because your app ended properly although not the way you wanted.



  • @SGaist Thanks again for the quick answer! But where should that report be? I don't think the app is exiting correctly, as running it before macdeployqt works fine. Also, i did not include another way to end de application myself, but pressing the close button. So if its ending without pressing that button, something is wrong, right? The application only crash when i run the *.app AFTER macdeployqt and loading a custom plugin. If i run it without macdeployqt, it works with or without plugin... if i run it without plugin, it also works. Only the combination of having used macdeployqt and loading the plugin makes the app crash.



  • Also, both windows and linux are working flawlessly.


  • Lifetime Qt Champion

    What plugins are you using ?

    As for the crash report, you should get a dialog automatically after the crash.

    What happens if you call "open your_app.app" on the command line ?



  • @SGaist It's a plugin i wrote myself for my application.
    I'm actually calling open <path_to_app> and nothing is printed out to the console.
    If i load the plugin, the application just closes.


  • Lifetime Qt Champion

    Start your application with the QT_DEBUG_PLUGINS environment variable set to 1. It will show you what is happening with your plugin.



  • @SGaist Hey, nothing appears aswell :(


  • Lifetime Qt Champion

    Ça you show the code dealing with your plugin ?



  • @SGaist Hi! yes, i can show all my code. In fact, both plugin and application are open source:

    https://github.com/azagaya/laigter
    https://github.com/azagaya/LaigterNormalBrushPlugin

    The revelant part of the app that loads the plugin, is on mainwindow.cpp:

    void MainWindow::on_actionLoadPlugins_triggered()
    {
      QString appData =
        QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
      QDir dir(appData);
      dir.cd("plugins");
      const auto entryList = dir.entryList(QDir::Files);
      foreach (QDockWidget *dock, plugin_docks_list){
        plugin_docks_list.removeOne(dock);
        delete dock;
      }
      foreach (QAction *action, ui->pluginToolBar->actions()){
        if (action->text() == tr("Load Plugins") || (action->text() == tr("Install Plugin"))) continue;
        ui->pluginToolBar->removeAction(action);
      }
      for (const QString &fileName : entryList) {
        QPluginLoader pl(dir.absoluteFilePath(fileName));
        BrushInterface *b = qobject_cast<BrushInterface *>( pl.instance());
        qDebug() << pl.errorString();
        if(b != nullptr){
          ui->openGLPreviewWidget->currentBrush = b;
          b->setProcessor(&processor);
          QAction *action = new QAction(b->getIcon(),b->getName());
          action->setCheckable(true);
          QDockWidget *pluginDock = new QDockWidget(b->getName(),this);
          QWidget *pluginGui = b->loadGUI();
    
          addDockWidget(Qt::LeftDockWidgetArea,pluginDock);
          pluginDock->setFloating(true);
          pluginDock->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);
    
          pluginDock->setWidget(pluginGui);
    
          pluginDock->setVisible(false);
          connect(action,SIGNAL(toggled(bool)),pluginDock,SLOT(setVisible(bool)));
    
          ui->pluginToolBar->addAction(action);
    
          plugin_docks_list.append(pluginDock);
    
        }
      }
    }
    

    This is the first time i make plugins for my apps. I save then in the appdata location, and then load from there.



  • Also, this is the interface:

    #ifndef BRUSHINTERFACE_H
    #define BRUSHINTERFACE_H
    
    #include <QtPlugin>
    
    QT_BEGIN_NAMESPACE
    class QImage;
    class QPainter;
    class QWidget;
    class QPainterPath;
    class QPoint;
    class QRect;
    class ImageProcessor;
    QT_END_NAMESPACE
    
    class BrushInterface
    {
      public:
      virtual void mousePress(const QPoint &pos) = 0;
      virtual void mouseMove(const QPoint &oldPos, const QPoint &newPos) = 0;
      virtual void mouseRelease(const QPoint &pos) = 0;
      virtual bool get_selected() = 0;
      virtual void set_selected(bool s) = 0;
      virtual QWidget *loadGUI(QWidget *parent = nullptr) = 0;
      virtual void setProcessor(ImageProcessor **processor) = 0;
      virtual QIcon getIcon() = 0;
      virtual QString getName() = 0;
      virtual QImage getBrushSprite() = 0;
      signals:
          void selected(BrushInterface *brush);
    };
    
    #define BrushInterface_iid "org.azagaya.laigter.plugins.BrushInterface/1.0"
    
    Q_DECLARE_INTERFACE(BrushInterface, BrushInterface_iid)
    
    #endif // BRUSHINTERFACE_H
    

  • Lifetime Qt Champion

    Your plugins path is a bit surprising. On macOS they should be in your app bundle but your are looking for them in your system. Is that really the case ?

    Did you already check the Plug and Paint example ?



  • @SGaist Yes, i checked it while i was working on the plugin in linux. The thing is that i want users to be able to "install/remove" plugins, and that when they download a new release, that plugins remain. So i tried using the appdata location in the system, and worked both in linux and windows. I don't want to include every single plugin in the bundle, because may be some plugins are only meant for contributors/patreons/etc. Is this possible with mac?
    Also, a friend of mine tried the app generated without using macdeployqt, and with all dependencies installed, and both the app and the plugin worked fine. The problem is that others users cannot use the app if i don't deploy with macdeployqt.



  • So, in mac i should try using like in plug & paint, and that the user reinstalls the plugins if they download a newer app, right? I could try that.


  • Lifetime Qt Champion

    Check your plugin with otool -L you'll see that the libraries it depends on are searched into your application bundle. Hence they will fail to load if you moved them around.



  • @SGaist thanks! otool -l libNormalBrush.dylib gives me this output:
    https://pastebin.com/9uk06Dqi
    It doesn't seem to look for them in the application bundle, but on the system, right? So that's what making it crash? it doesn't find the libs?



  • @SGaist Well, i finally managed to get an error, running the executable inside the .app directly from console:

    
    "/Users/mac/Library/Application Support/laigter"
    objc[95815]: Class CaptureDelegate is implemented in both /Users/mac/laigter-1.8/laigter.app/Contents/Frameworks/libopencv_videoio.4.1.dylib (0x1046d1ae0) and /usr/local/opt/opencv/lib/libopencv_videoio.4.1.dylib (0x12745aae0). One of the two will be used. Which one is undefined.
    objc[95815]: Class CVWindow is implemented in both /Users/mac/laigter-1.8/laigter.app/Contents/Frameworks/libopencv_highgui.4.1.dylib (0x104699330) and /usr/local/opt/opencv/lib/libopencv_highgui.4.1.dylib (0x127420330). One of the two will be used. Which one is undefined.
    objc[95815]: Class CVView is implemented in both /Users/mac/laigter-1.8/laigter.app/Contents/Frameworks/libopencv_highgui.4.1.dylib (0x104699358) and /usr/local/opt/opencv/lib/libopencv_highgui.4.1.dylib (0x127420358). One of the two will be used. Which one is undefined.
    objc[95815]: Class CVSlider is implemented in both /Users/mac/laigter-1.8/laigter.app/Contents/Frameworks/libopencv_highgui.4.1.dylib (0x104699380) and /usr/local/opt/opencv/lib/libopencv_highgui.4.1.dylib (0x127420380). One of the two will be used. Which one is undefined.
    ERROR: something wrong with flag 'flagfile' in file '/tmp/gflags-20190105-77846-1pdnfpc/gflags-2.2.2/src/gflags.cc'.  One possibility: file '/tmp/gflags-20190105-77846-1pdnfpc/gflags-2.2.2/src/gflags.cc' is being linked both statically and dynamically into this executable.
    

    That error arrises just when i load the plugin into the application. So i what i understand here is that i must change where the plugin is looking for libs? Can i change that?


  • Lifetime Qt Champion

    Yes, you can change that use install_name_tool for that. That's what macdeployqt uses to do its job.



  • @SGaist Thanks! i'll try it tonight. So just so just to be sure, i must change where the plugin libNormalBrush.dylib looks for the libs, and change them to rpath?
    something like:

    install_name_tool -change each_one_of_the_libs.dylib @rpath/../lib/each_of_the_libs.dylib libNormalBrush.dylib 
    

    Right?


  • Lifetime Qt Champion

    Check the Qt plugins to see where they are looking for. You also have to check where your OpenCV libraries are stored in the bundle.



  • @SGaist Well, i tried with install_name_tool and changed the path correctly (i think) but it stills fails. I think the problem is this line:

    ERROR: something wrong with flag 'flagfile' in file '/tmp/gflags-20190105-77846-1pdnfpc/gflags-2.2.2/src/gflags.cc'.  One possibility: file '/tmp/gflags-20190105-77846-1pdnfpc/gflags-2.2.2/src/gflags.cc' is being linked both statically and dynamically into this executable.
    

    but i dont have a clue of what it means. I never had this problem before.


  • Lifetime Qt Champion

    What libraries are you using for that plugin ?



  • @SGaist Appart from qt libs, i'm using a custom class included in the application. That class uses some opencv libs, so the plugin itself seems to be linking to them. This is what otool says:

    	/usr/local/opt/opencv/lib/libopencv_gapi.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_stitching.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_aruco.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_bgsegm.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_bioinspired.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_ccalib.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_dnn_objdetect.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_dpm.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_face.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_freetype.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_fuzzy.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_hfs.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_img_hash.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_line_descriptor.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_quality.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_reg.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_rgbd.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_saliency.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_sfm.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_stereo.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_structured_light.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_phase_unwrapping.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_superres.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_optflow.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_surface_matching.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_tracking.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_datasets.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_text.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_dnn.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_plot.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_videostab.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_video.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_xfeatures2d.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_shape.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_ml.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_ximgproc.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_xobjdetect.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_objdetect.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_calib3d.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_features2d.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_highgui.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_videoio.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_imgcodecs.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_flann.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_xphoto.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_photo.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_imgproc.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	/usr/local/opt/opencv/lib/libopencv_core.4.1.dylib (compatibility version 4.1.0, current version 4.1.0)
    	@rpath/QtWidgets.framework/Versions/5/QtWidgets (compatibility version 5.13.0, current version 5.13.0)
    	@rpath/QtGui.framework/Versions/5/QtGui (compatibility version 5.13.0, current version 5.13.0)
    	@rpath/QtCore.framework/Versions/5/QtCore (compatibility version 5.13.0, current version 5.13.0)
    	/System/Library/Frameworks/DiskArbitration.framework/Versions/A/DiskArbitration (compatibility version 1.0.0, current version 1.0.0)
    	/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit (compatibility version 1.0.0, current version 275.0.0)
    	/System/Library/Frameworks/OpenGL.framework/Versions/A/OpenGL (compatibility version 1.0.0, current version 1.0.0)
    	/System/Library/Frameworks/AGL.framework/Versions/A/AGL (compatibility version 1.0.0, current version 1.0.0)
    	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.0)
    	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.0.0)
    


  • @SGaist That output from otool is previous i used install_name_tool to change the path. I looked inside the app and they are located in the same place where QtWidgets.framework and others are located, so i changed the path to @rpath
    I dont have the mac right now (its borrowed), but i can send you the updated otool output if needed.


  • Lifetime Qt Champion

    Yes, that would be nice.

    Just for the sake of testing (and to ensure I am not missing anything), Does it also crash if you keep the plugin within the bundle with the other plugins ?



  • @SGaist ill try that and write you back! I didnt try the other day because i though changing the paths would work.
    Thanks a lot!


Log in to reply