Qt app bundle for MacOS is too slow - macos

I build my Qt application on Mac (Mavericks), using CMake. It creates a bundle file in the build directory called SquiggleMark.app.
Next I run a script that copies libraries into the bundle, just Qt framework and libqcocoa.dylib files.
Finally I use iDMG to create a dmg file.
Now if I mount this dmg file and run my app from the mount, it runs fine. But if I move the dmg to /Applications and run it from Finder > Applications, it takes very long time, couple of minutes to launch.
How can I debug this?
I suspect it is taking too long to find the libraries in Finder, but I am not sure.
When I run the app from terminal, by typing "/Applications/SquiggleMark/Contents/MacOS/SquiggleMark", it also works fine.
The dmg is here You can try it out and tell me if you are seeing the same long load time as I am.
My bundling script has commands like this:
install_name_tool -id #executable_path/../Frameworks/QtWidgets $BUNDLE/Contents/Frameworks/QtWidgets
install_name_tool -change $QTDIR/clang_64/lib/QtWidgets.framework/Versions/5/QtWidgets #executable_path/../Frameworks/QtWidgets $BUNDLE/Contents/MacOS/$APP
I am not posting the whole script because it is too long, however if someone wants it, I can put it up here.

Related

How to build an installer for a python application for Mac

I have created a python application and can install it perfectly fine on Windows. I run pyinstaller to generate the executable, and then use NSIS to create an actual installer. I run the installer and it installs the application to my Program Files folder and gives me a nice desktop shortcut, etc.
What is the process to do the same for Mac? Essentially, I want to give my user a single file. When they run the file, it installs my program and any necessary libraries, and let's them launch it with a single click. I believe on Mac this is done with a .dmg or a .pkg file. What software/tools do I need to generate such a file? Do I need to restructure the project in anyway to create this?
For more info, pyinstaller creates a folder 'dist' which contains the unix executable of the application, and copies of python and any required libraries.
Note that I do not want to use the onefile option for pyinstaller because it would take a while to unpack everything each time the program is ran.

Is There Macdeployqt for QT Command Line Executable Binary Without App Bundle?

I'm trying to build a command line tool on Mac that doesn't result in .app bundle.
When I run make release, it just gives an executable file since it's a command line tool for terminal.
I understand that macdeployqt lets you package all the necessary files for .app to run without qt installed on another machine.
Is there similar tool for just binary executable?
When I pass the executable to macdeployqt, I get "ERROR: Could not find bundle binary for ...".
macdeployqt is run against an existing .app bundle and handles most of the library collection and install_name_tool business to make the bundle deployable. Even if you were to utilize this tool, you would end up customizing the binary's install_name info manually to suit your purpose.
https://github.com/SCG82/macdylibbundler will bundle an app and fix up the install names/rpaths. Disclaimer: I'm the developer.

On OS X, difference between drag & drop install vs copying to /Applications

I'm trying to automate the install of Xcode on an OS X machine. I've come across this question that got me most of the way.
The script given in the second answer gets the appropriate dmg mounted, and then uses installer to install the pkg. Except these days (e.g. version 7.3.1) Xcode is given as an app bundle inside the dmg, so there is no pkg to install. So I tried to simply copy it to /Applications via
cp -Rf /Volumes/Xcode/Xcode.app /Applications/
The resulting Xcode in my /Applications folder is 9.1 GB. But if I simply rename that bundle, manually open the dmg, and then drag & drop Xcode onto the Application shortcut, I end up with an Xcode that is 10.51 GB in size. Yet when I ask opendiff to compare the two, it tells me the contents are identical...
Does dragging & dropping from a dmg do something else under the hood, besides simply copying the app into /Applications? If so, is there a way to achieve the same via the command line?

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.

.app OSX package problems on removable media

So from what little I understand about packaging for Macs, I see that the actual program that launches is the one defined under the CFBundleExecutable key in Info.plist.
<key>CFBundleExecutable</key>
<string>JavaApplicationStub</string>
Now, my app doesnt work if /APP/Content/MacOS/JavaApplicationStub is not chmodded +x (It just fails silently without doing anything, which is a pain!).
Fair enough, its not executable I guess. But its a big problem if you are copying the app from somewhere that dosent support +x properties on files; such as windows, fat32 USB keys, CDROMs, websites, zip files, etc...
What can I do in these instances to make the app able to run? Manually setting the execute bit is not an option.
There's got to be people who run Mac apps off CD, at the very least!
I think your only option is to package the APP bundle into a DMG file, or tar.
DMG is more standard and just as easy to do as using tar or zipping. The command line we use is:
hdiutil create -srcfolder Last.fm.app -format UDZO -imagekey zlib-level=9 -scrub Last.fm.dmg
You can tar from any platform, (even Windows, if you install cygwin, or use the GNU standalone, http://gnuwin32.sourceforge.net/packages/gtar.htm)
tar cf app.tar app_directory
With gzip compression:
tar czf app.tar.gz app_directory
#mxcl, that works, sort of, thanks. However, you need to be on a Mac to run hdiutil :(.
Also, it mucks up the paths of the app... there were some files(like the db file) that were not inside the .app folder, and thus are not included in the .DMG file.
Im building on windows, and the app is getting deployed to removable media. The whole point is to avoid installing anything.
The app runs on windows aswell, so there is a windows .exe alongside the mac.app on the root of the disk. There is also a sqllite.db file that both versions of the application share. Multi-platform is hard :/

Resources