Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deploying Qt Frameworks with Mac app and usage of otool

I have a problem deploying Qt frameworks with my Mac app, and I hope some will have a clue why I get this error, when I run the app on clean Mac, i.e. not a developer Mac.

OS: 10.7 .2 and using XCode

Error msg:

Library not loaded: @loader_path/../Frameworks/QtCore.framework/Versions/4.0/QtCore
Referenced from:/Users/someUser/Downloads/MainApp.app/Contents/Resources/Lib/Library.bundle/Contents/MacOS/../Frameworks/../Frameworks/QtXml.framework/Versions/4/QtXml

Clearly something is wrong since the QtXml is referenced from /../Frameworks/../Frameworks, which doesn’t exists.

This is the set up: I have a dylib that uses QtCore and QtXml (not by my choosing, but for now I need those two frameworks), the dylib is used in a NSBundle, which is loaded by the main app, the bundle is located in the resource folder. The dylib is moved by Copy Files Build Phase to the folder Contents/Frameworks and with otool the install_name is set to (as stated by http://doc.qt.digia.com/4.3/deployment-mac.html):

@loader_path/../Frameworks/QtCore.framework/Versions/4.0/QtCore
@loader_path/../Frameworks/QtXml.framework/Versions/4/QtXml

then the Qt frameworks are moved to Contents/Frameworks and the install_name of the is set to:

@executable_path/../Frameworks/QtCore.framework/Versions/4.0/QtCore

and for the QtXml @executable_path/../Frameworks/QtXml.framework/Versions/4/QtXml with reference to QtCore: @executable_path/../Frameworks/QtCore.framework/Versions/4.0/QtCore

Now when I run the app on the developer mac it clearly works since Qt is installed, but when moved to a clean mac I get the error msg, readable in the Console app. I’ve tried to change the executable_path to loader_path, but this didn’t work. I have no idea what I’m doing wrong or why it won't for, and have not been able to find anything on Google, of course I could be looking at the wrong places. Any ideas how to fix this problem?

This is the entire error message:

MainApp: Error Domain=NSCocoaErrorDomain Code=3587 "The bundle “Library” couldn’t be loaded because it is damaged or missing necessary resources."
(dlopen_preflight(/Users/someUser/Downloads/MainApp.app/Contents/Resources/Lib/Library.bundle/ Contents/MacOS/Library): Library not loaded:
@loader_path/../Frameworks/QtCore.framework/Versions/4.0/QtCore Referenced from: /Users/ someUser /Downloads/ MainApp.app/Contents/Resources/Lib/Library.bundle/Contents/MacOS/../Frameworks/../Frameworks/QtXml.framework/Versions/4/QtXml Reason: image not found) UserInfo=0x107c5d5d0 {NSLocalizedFailureReason=The bundle is damaged or missing necessary resources., NSLocalizedRecoverySuggestion=Try reinstalling the bundle., NSFilePath=/Users/someUser/Downloads/MainApp.app/Contents/Resources/Lib/Library.bundle/Contents/MacOS/Library, NSDebugDescription=dlopen_preflight(/Users/someUser /Downloads/MainApp.app/Contents/Resources/Lib/Library.bundle/Contents/MacOS/Library): Library not loaded: @loader_path/../Frameworks/QtCore.framework/Versions/4.0/QtCore
Referenced from: /Users/someUser/Downloads/MainApp.app/Contents/Resources/Lib/Library.bundle/Contents/MacOS/../Frameworks/../Frameworks/QtXml.framework/Versions/4/QtXml Reason: image not found, NSBundlePath=/Users/someUser/Downloads/MainApp.app/Contents/Resources/Lib/Library.bundle, NSLocalizedDescription=The bundle “Library” couldn’t be loaded because it is damaged or missing necessary resources.}

like image 522
Steffen Andersen Avatar asked Jan 30 '12 08:01

Steffen Andersen


2 Answers

On the development mac everything works because the Qt libraries are installed. On any mac you ship the app to, though, this likely won't be the case. The Qt suite comes with a tool called macdeployqt to fix this. So in a terminal, after you've compiled your application, do something like:

# cd my-cool-app-Desktop
# macdeployqt my-cool-app.app

Note that it can also be used to create a .dmg file for shipping everything together:

# cd my-cool-app-Desktop
# macdeployqt my-cool-app.app -dmg

Once you've done that, the .app directory or .dmg file can be given to someone else without Qt installed to use and run as they normally would.

The one caveat is that the next time you try to run it on your developer machine, it may complain about multiple shared libraries installed. So once you've copied it else where in order to distribute it, remove the entire .app directory and let qtcreator (or whatever) rebuild it.

like image 98
Wes Hardaker Avatar answered Oct 19 '22 23:10

Wes Hardaker


UPDATE

As stated compiling QT to static libs is the way to go. With the release of Mavericks (10.9) we need to codesign frameworks as well (http://furbo.org/2013/10/17/code-signing-and-mavericks/), and with QT4.8.5 there are some issues (https://bugreports.qt-project.org/browse/QTBUG-32896). Even with suggested fixes I still had some issues when running the app on a clean machine. Therefore, I ended up with compiling Qt5.2 to staticlibs, link them in the app, and codesign them.

OLD

Problem sovled, I moved the Qt-frameworks into the app bundle in Contents/Frameworks and with otool set the path to @executable_path/../Frameworks, i.e. moved it out of my library bundle. Yes the solution is simple, but I'm still not sure why the library executable couldn't find the frameworks when using @loader_path.

The best solution would probably be to use a static library and not wrap it in a bundle...you learn everyday ;)

like image 28
Steffen Andersen Avatar answered Oct 20 '22 01:10

Steffen Andersen