Qt + CMake for OSX Bundle: Cocoa Platform Plugin - macos

I'm trying to make a bundle for a Qt based application using CMake.
Things seem to be working fine in terms of linkages, but trying to run the app gives me the error:
This application failed to start because it could not find or load the Qt platform plugin "cocoa".
Available platform plugins are: cocoa.
I'm not sure what this means as the two lines of output seem conflicting. The directory platforms/ (which contains libqcocoa.dylib) is in MyApp/Contents/Resources/bin/. Note that the MyApp executable is there as well.

While the platform library was in the correct position relative to the executable, the libqcocoa library was expecting other Qt libraries to which it was linked to be in specific directories. I used a script with install_name_tool -change commands to modify these paths.

Related

OSX: start app with runtime-dependent dylibs

OSX 10.10 Yosemite.
My application depends on Intel IPP.
At compile time it depends on 2 dylibs, but these depend from other dylibs, which are loaded at runtime (and not displayed in otool -L) . When starting my application does not find these libraries.
I do not understand how can I specify for my app (or for the compile time dependent dylibs) a folder to search a path for runtime dylibs.
As far as I can understand, it is necessary to use rpath. But what exactly should be done? How to set runtime search path? Do I need to set a 'rpath' for the executable file or for the dylibs?
I think you will have to use install_name_tool command to add the dylib.
Don't think you can setup a folder that can magically load all the dylib in it. It's against the purpose of code signing and security.

How do I deploy Assistant with my app on Mac without deploying multiple copies of Qt Frameworks?

I am trying to deploy a Qt application that uses the Assistant to show help, on mac (OS X 10.6-10.9, Qt 4.8)
QStringList args = "-collectionFile " + "my_help_file";
QString app = "path/"+"Assistant.app";
m_helpProcess->start(app, args);
I placed the Assistant.app inside the Resources folder.
Since I deploy the app on a system with no qt installed, I placed all he QT dependencies in Contents/Frameworks, and ran install_name_tool
# for QtCore:
install_name_tool -id #executable_path/../Frameworks/QtCore.framework/Version/QtCore.framework/Versions/4/QtCore xxx.app/Contents/Frameworks/QtCore.framework/Versions/4/QtCore
install_name_tool -change QtCore.framework/Versions/4/QtCore #executable_path/../Frameworks/QtCore.framework/Versions/4/QtCore xxx.app/Contents/MacOs/xxx
install_name_tool -change QtCore.framework/Versions/4/QtCore #executable_path/../Frameworks/QtCore.framework/Versions/4/QtCore xxx.app/Contents/Resources/Assistant.app/Contents/MacOS/Assistant
The app gets it, it is functional, but Assistant doesn't... obviously it is a different level.
I don't want to place multiple copies of the frameworks... besides I am sure there will be conflicts if i do...
Calling Assistant without its bundle didn't work... (I would love to place the executable next to the xxx executable)
Since I guess I set the id for the Frameworks as one directory down from #executable_path, I can't tell help to look elsewhere...
How do I link the Assistant properly with the Frameworks ?
Note: I have tried:
# for QtCore:
install_name_tool -id #executable_path/../Frameworks/QtCore.framework/Version/QtCore.framework/Versions/4/QtCore xxx.app/Contents/Frameworks/QtCore.framework/Versions/4/QtCore
install_name_tool -change QtCore.framework/Versions/4/QtCore #executable_path/../Frameworks/QtCore.framework/Versions/4/QtCore xxx.app/Contents/MacOs/xxx
install_name_tool -change QtCore.framework/Versions/4/QtCore #executable_path/../../../Frameworks/QtCore.framework/Versions/4/QtCore xxx.app/Contents/Resources/Assistant.app/Contents/MacOS/Assistant
Did not find libraries... I guess the id has to match the path... but for a single instance of the lib, it just can't...
I also tried to make symbolic link (alias ?) to the Qt library, in the location where Assistant will look... It tried and failed, complaining of a malformed file.
Update to answer comment:
Running otool -L on the assistant in the Assistant bundle in the Resources folder:
#executable_path/../Frameworks/QtCore.framework/Versions/4/QtCore
And the Assistant can't find the library which really is at
#executable_path/../../../Frameworks/QtCore.framework/Versions/4/QtCore
Unexpectedly, the Assistant opened correctly even from outside the QT Creator.. Once I gave both the assistant and the resource file absolute paths. (I could have done that for either the Assistant executable or an entire bundle)
I copied the executable Assistant inside the same folder as my app executable.
Of course, adding dependent libraries and setting the link paths to #executable_path/../Frameworks was required, like for deploying any app. (I just did it manually, not with macdeployqt because macdeployqt failed to copy the plugins)
And quite important, getting the sqldrivers Plugin required for Assistant was needed. And... that was a tough one... setting the dependencies for the Plugin on Frameworks as well.
It would have been great to have the Assistant in its own bundle (inside Resources)... but with the Qt library dependencies still in the resources of the main bundle, to avoid copying the same libraries multiple times. I was unable to do that. Placing Qt frameworks outside the bundle was not an option, since I cannot rely on users not to remove items or install other versions.

Where does mac osx app require dependent libraries?

I have built a Qt project under mac, but I have problems executing.
Its dependencies have several dylib .
When building the project, the make tool only asks for one of the libs (for example lib.1.0.0,dylib out of lib.1.dylib, lib.1.0.dylib, lib.1.0.0.dylib, lib.1.0.0.0.dylib) - so I know to put it in the .pro file
Some look like links - but it is not always the lib version that looks like a file that is required as a dependency.
But at run time, I don't know which dylib I need, and where to put it.
I tried to place all 4 lib versions in the folder where the app was created - the project folder - but the app didn't execute.
Having done the same in Linux, I had to put the libs in a place set on path - like /usr/local/libs
Where does mac like its libs (shared libs ?) in order to run ?
You should read this document on deploying Qt applications. It will answer your questions. Moving your libraries to a system library path is usually not a good idea.
http://qt-project.org/doc/qt-5/macosx-deployment.html
To sum this up though you need to change the binaries to tell them where the libs are using the otool command.

Trace dylib loading on Mac OSX

I'm trying to build a Qt-based application on Mac OSX, and something in my application bundle is pulling in a Qt library from /Library rather than from the application bundle.
I've done this successfully in the past, so I know about using install_name_tool to link applications and libraries to the bundle versions of libraries. I've done this, but I must be missing something. I've tried setting DYLD_PRINT_LIBRARIES, but I'm not really sure how this helps: I can see which Qt library is being pulled in from /Library first (QtXml), but I don't know which file in the bundle is pulling in this library.
Is there some trick to tracing back which file is loading a particular library?
Use otool utility to see what libraries are used by your app and where the app expects to find them:
otool -L yourApp.app/Contents/MacOS/yourApp

Automatically include Qt libraries in the .app bundle deploying on Mac

I am using Qt Creator to deploy my Qt application. On Mac, I'd like to include the required Qt libraries in the .app bundle. Is there any way to do it automatically using Qt Creator? Should I do it using the command-line? In that case, how should I do it?
The macdeployqt command line tool will add all the necessary Qt libraries that your Qt project references.
If you require any other, 3rd party libraries, you'll need to copy these manually and set the paths to them using the install_name_tool command.
You can check which libraries your application references using the otool command. For example: -
otool -L MyApplication.app/Contents/MacOS/MyApplication
For Qt Creator, I tend to write a script that adds the necessary libraries and calls macdeployqt and then under Projects, add a build step which calls the script.
An example script that would just add the Qt libraries would look something like this: -
#!/bin/bash
pwd
echo Copying QT libraries...
macdeployqt ./MyApplication.app
You can simply run macdeployqt foo.app. Qt Creator does not support this feature off-hand either. However, you can inject custom commands into your process in the QtCreator project settings.
It does not support QML just yet though. There are patches under codereview where it is coming. See the following link for details:
https://codereview.qt-project.org/#q,status:open+project:qt/qttools,n,z
Note: macdeployqt should not be used for usual development and debug! It should be only used when deploying. Otherwise, it is executed each time for building even if you just recompile the code due to a minor change for testing. This can slow down that process, but as for deploying, it should be alright.
On QT6 I was able to do it entirely within QT Creator:
In Projects/Build, add a custom build step after 'make' (probably only want to do this for your 'release' configuration):
Command: %{Qt:QT_HOST_PREFIX}/bin/macdeployqt
Arguments: %{ActiveProject:BuildConfig:Path}/%{ActiveProject:Name}.app - qmldir=%{ActiveProject:NativePath}
Working Directory: %{buildDir}
I was able to test it by airdropping the resulting .app onto my test machine.
reference: https://doc.qt.io/qt-6/macos-deployment.html#macdeploy

Resources