Qt 5.3 (and 5.4) Mac application crashes on startup after using macdeployqt; .app unable to load plugin "cocoa"
-
I'm developing a Qt application on my iMac (a Mac mini with OS X Yosemite) using Qt v5.3 (and later v5.4 after uninstalling v5.3 with the MaintenanceTool)
My application (myapp.app) runs correctly from QtCreator and when launched outside of Qt either from the terminal or from Finder.
However, after using macdeployqt the .app will crash with the following error:
@This application failed to start because it could not find or load the Qt platform plugin "cocoa".@
A listing of the libraries and frameworks that were loaded during startup is given below.
A brief synopsis of the problem is as follows:
- Qt frameworks are loaded (QtCore, QtGui, and QtWidgets) from inside the bundle
- /usr/lib/... and /System/Library/... libraries and frameworks are loaded from outside the bundle
- libqcocoa.dylib plugin is loaded in error from outside the bundle (should have been loaded from inside the bundle)
- a second set of Qt frameworks are loaded from outside the bundle
- the .app crashes with a failure to load libqcocoa error
I uninstalled Qt5.3 (using the MaintenanceTool) and reinstalled Qt5.4 -- same problem plus a new problem:
@myimac:release Dean$ macdeployqt myapp.app
ERROR: no file at "/opt/local/lib/libz.1.dylib"
ERROR: no file at "/opt/local/lib/libz.1.dylib"
ERROR: no file at "/opt/local/lib/libz.1.dylib"
ERROR: no file at "/opt/local/lib/libz.1.dylib"
myimac:release Dean$@(I don't have a /opt/ folder on my machine)
I renamed the Qt installation from Qt/5.4/... to Qt0/5.4/... to hide its binaries from my .app but the app still crashes, this time because it can't find the libqcocoa.dylib file.
I've used otool -L on every library and framework inside the bundle and none of them reference my Qt installation binaries. They reference either executable_path/... or my system files (i.e. /usr/lib/... and /System/Library/...)
[I'm assuming that one of the system binaries is referencing the external cocoa plugin and that when it is loaded the external cocoa plugin loads the external Qt frameworks because it wasn't patched by macdeployqt]
My question is, how do I determine which library is loading libqcocoa.dylib and why is it being loaded from outside the bundle when it exists and was placed there by macdeployqt?
@myimac:MacOS Dean$ export DYLD_PRINT_LIBRARIES=1
myimac:MacOS Dean$ ./myapp
dyld: loaded: /Users/Dean/Products/.../myapp.app/Contents/MacOS/./myapp
dyld: loaded: /Users/Dean/Products/.../myapp.app/Contents/MacOS/./../Frameworks/QtWidgets.framework/Versions/5/QtWidgets
dyld: loaded: /Users/Dean/Products/.../myapp.app/Contents/MacOS/./../Frameworks/QtGui.framework/Versions/5/QtGui
dyld: loaded: /Users/Dean/Products/.../myapp.app/Contents/MacOS/./../Frameworks/QtCore.framework/Versions/5/QtCore
dyld: loaded: /System/Library/Frameworks/DiskArbitration.framework/Versions/A/DiskArbitration
dyld: loaded: /System/Library/Frameworks/IOKit.framework/Versions/A/IOKit
dyld: loaded: /System/Library/Frameworks/OpenGL.framework/Versions/A/OpenGL
dyld: loaded: /System/Library/Frameworks/AGL.framework/Versions/A/AGL...
dyld: loaded: /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/CommonPanels.framework/Versions/A/CommonPanels
dyld: loaded: /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/Help.framework/Versions/A/Help
dyld: loaded: /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/ImageCapture.framework/Versions/A/ImageCapture
dyld: loaded: /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/OpenScripting.framework/Versions/A/OpenScripting
dyld: loaded: /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/Print.framework/Versions/A/Print
dyld: loaded: /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/SecurityHI.framework/Versions/A/SecurityHI
dyld: loaded: /Users/Dean/Qt/5.4/clang_64/plugins/platforms/libqcocoa.dylib
dyld: loaded: /Users/Dean/Qt/5.4/clang_64/lib/QtGui.framework/Versions/5/QtGui
dyld: loaded: /Users/Dean/Qt/5.4/clang_64/lib/QtCore.framework/Versions/5/QtCore
dyld: loaded: /Users/Dean/Qt/5.4/clang_64/lib/QtPrintSupport.framework/Versions/5/QtPrintSupport
dyld: loaded: /Users/Dean/Qt/5.4/clang_64/lib/QtWidgets.framework/Versions/5/QtWidgets
objc[5045]: Class NotificationReceiver is implemented in both /Users/Dean/Products/.../myapp.app/Contents/Frameworks/QtWidgets.framework/Versions/5/QtWidgets and /Users/Dean/Qt/5.4/clang_64/lib/QtWidgets.framework/Versions/5/QtWidgets. One of the two will be used. Which one is undefined.
QObject::moveToThread: Current thread (0x101a1dfc0) is not the object's thread (0x101b02770).
Cannot move to target thread (0x101a1dfc0)On Mac OS X, you might be loading two sets of Qt binaries into the same process. Check that all plugins are compiled against the right Qt binaries. Export DYLD_PRINT_LIBRARIES=1 and check that only one set of binaries are being loaded.
This application failed to start because it could not find or load the Qt platform plugin "cocoa".Available platform plugins are: cocoa, minimal, offscreen.@
-
Hi, once you've run macdeployqt on your app folder, then next time you use Qt Creator to compile and launch your app, this error "cocoa"-plugin will invariably occur.
My understanding is that macdeployqt is meant to be used on your app once you've done working with it in Qt Creator and want to copy the app folder to another Mac.
If you change your mind and want to resume working with it in Qt Creator, just delete the app folder and you'll be fine (I write more about this interaction between macdeployqt and Qt Creator in my "blog":http://www.tripleboot.org/?p=138#Mac )Oh also, about those 4 error lines: no file at "/opt/local/lib/libz.1.dylib it's a "known bug":https://bugreports.qt.io/browse/QTBUG-43100 in 5.4 that hopefully will be fixed 5.4.1
-
Thanks hskoglund. My intent is as you've said, "macdeployqt is meant to be used on your app once you’ve done working with it in Qt Creator and want to copy the app folder to another Mac."
In my case, I'm trying to run my app after macdeployqt has been run on it to verify that it works as a standalone bundle -- at which point I'll then make it available for use on other Macs. But I can't get it to run on my Mac, which is why I renamed the Qt/5.4 folder to Qt0/5.4 -- to simulate running the bundle on a Mac where it wouldn't find a Qt installation. I'll try copying the bundle to a Mac that doesn't have Qt installed on it, but I'm pretty sure it will still fail.
Perhaps my biggest question is this, "When I try to launch my .app from Finder or the Terminal after macdeployqt has been run on it, why is libqcocoa.dylib being loaded from my Qt installation instead of being loaded from @executable_path/../PlugIns/platforms/libqcocoa.dylib?"
Related to this, I don't see a dependency on libqcocoa.dylib reported anywhere by otool -L. None of the system binaries (/System/Library or usr/lib) reference it and none of the frameworks, plugins, or other .dylibs inside the bundle reference it. Is there a .pro file setting that I'm omitting that is required for my .app to be compatible with macdeployqt?
Regarding the "/opt/local/lib/libz.1.dylib" issue -- thanks for pointing out that it's a known bug. I'll look forward to v5.4.1 :)
And thanks again for your reply.
-dean -
Hi, I also have 5.4 installed on my Mac, just tried building a simple HelloQt Widgets app and then running macdeployqt on it (same as you did), the app still works fine for me as long as I don't start Qt Creator and edit/recompile the app. (Also regardless if I rename my Qt to Qt0 or not.) So something is definitely fishy with your macdeployqt.
Now about how Qt mysteriously locates that libqcocoa.dylib: it uses an algorithm that is universal for all platforms, i.e. the same for Windows, Linux and Mac, I write about "here in my blog":http://www.tripleboot.org/?p=536#PluginDLLs, but a short version is, that Qt when it starts your app builds a list of directories where plugins such as libqcocoa.dylib reside.
On the Mac when you've run macdeployqt a qt.conf file is used to tell Qt where to find the plugins, and that qt.conf file should have been written to the Resources folder by macdeployqt. (Qt Creator creates a Resource folder that only contains a zerolength file empty.lproj.)
But in your case it seems that no qt.conf has been created? And that's why libqcocoa.dylib is loaded from the fallback location (the installation directory). -
Thanks. My .app contains a Contents/Resources/qt.conf with contents:
@[Paths]
Plugins = PlugIns
Imports = Resources/qml
Qml2Imports = Resources/qml@I'm assuming that since my libqcocoa.dylib is located in Contents/PlugIns/platforms that it will be found through the "Plugins = PlugIns" line (i.e. that the path is recursive to sub-folders).
I'll read your blog and see if it may provide additional hints.
-
-
I found the cause of the problem! Thanks for the hint provided in your "blog":http://www.tripleboot.org/?p=536#PluginDLLs and the tip to use "export QT_DEBUG_PLUGINS=1" to trace plugin loading (plus Qt's error message recommending the use of "export DYLD_PRINT_LIBRARIES=1" to trace dylib loading).
You mentioned in your blog, "You can also specify a plugin path in your code, but since Qt loads the plugins when QApplication is constructed, your window of opportunity is to do it before QApplication’s constructor is called."
In my case, my project had been originally written in Qt 4.8.2 and was updated for Qt 5.3. My startup sequence in main(), carried over from 4.8.2 and updated to use the Fusion style, was as follows:
@int main(int argc, char *argv[])
{
QApplication::setStyle(QStyleFactory::create("Fusion"));
QApplication::setPalette(QApplication::style()->standardPalette());QApplication app(argc, argv);
...
}@The problem was that the call to QStyleFactory::create() occurred before the QApplication constructor was called and QStyleFactory looked for libqcocoa.dylib directly in the default location -- my Qt installation.
Rearranging my startup sequence so that the QApplication constructor was called first fixed my problem.
@int main(int argc, char *argv[])
{
QApplication app(argc, argv);QApplication::setStyle(QStyleFactory::create("Fusion")); QApplication::setPalette(QApplication::style()->standardPalette());
...
}@Thank you again for all your help!
-
Hi,
Out of curiosity, did it work on other platforms ? AFAIK, nothing GUI related should be done prior creating a QApplication, so you really had luck if didn't crash anywhere before
-
@d.terhaar Thanks! This fixed me on this post:
https://forum.qt.io/topic/61001/broken-qt-5-5-macdeployqt/3
I moved my Fusion style line AFTER the
QApplication a(argc, argv);
line, unlike previous documentation I had read for this, and the problem went away. I was now able to deploy without Cocoa issues. I had been racking my brains for 3 hours on this. I'm so glad you did the difficult digging to find the fix.