Deploying QT app on OS X and linux - qt

Whats the best way to deploy a QT app? I've read the documentation hosted at trolltech but is it better to link with a static library or the dynamic libraries and have the user install the framework? I don't really want anyone using my app to have to download a 160mb framework just to run a simple gui frontend.

On OS X it's a good way to do a dynamic build and post-process the resulting ".app" with the macdeployqt tool which comes with Qt starting with 4.5.
This will copy the Qt frameworks used by your application into the application bundle, which results in a larger package than building a static version of your application.
Here is what you can do to make sure you get the smallest file size possibly in a dynamic build:
First off, make sure you only include the stuff you need (in the project.pro file's QT += core gui network xml lines).
Open the application bundle and remove any unneeded "Qt Plugins" from the bundle. macdeployqt automatically compies all the Qt plugins in there, which can be kind of bulky.
Make sure you are building your application in release mode. Otherwise your application might be linked against the debug libraries of the Qt4 framework, and they are really big (for instance, well over 90 MB for the debug library vs. 16 MB of a release variant without debugging symbols). This might be what happened in your case.
If you have a large application binary, you can use UPX to compress your executable file by 40-50%.
Other than that, you should use compressed disk images to deploy your application.
One of my projects uses QtGui, QtNetwork, QtCore and QtXml and the resulting bundle is about 16 MB in size.
Hope that helps.

Unfortunately you will have to include the Qt libraries you need into your own bundle, as you cannot expect your users to have Qt installed on Mac (whereas on Linux packaging systems allow you to require at least a given version of Qt.
There is a nice tool to help you with that, which is called macdeployqt. You just need to invoke it on your bundle application and it will pack the required libraries, changing the linkage of your binary to refer to them. Without it, making bundles for Mac is a real pain (it still is, but considerably less though).
http://doc.trolltech.com/4.6/deployment-mac.html#the-mac-deployment-tool
Afterwards, you can make a .dmg image as you would do with any other app. There is an option in macdeployqt that builds a basic one.

On Linux, it's better to rely on the OS's copy of Qt, as it's almost certainly installed - for OS X, almost all apps use a statically compiled library.

Related

Build application and Qt from source using cmake

I'm trying to set up building an application that uses qt5.6 in a way that both qt and the application are build from source (using the ninja generator, with visual studio compiler on windows and clang on mac).
I'm stuck at find_package(Qt5Core ..) : when Qt is not build yet, it will not be found. And because it's not found, the generate cmake file is not complete.
I think I need a setup where it generates a ninja files that, when build, builds Qt and then regenerates the ninja file (and at this point it would find qt) before continuing the build.
Or any other way in which I can build Qt+application from source, so that if I change something in Qt, it is automatically rebuild.
How should I set up my cmake file(s) to do that?
You could use CMake's ExternalProject command to invoke CMake from within CMake. You can specify dependencies there, so that your application will only be built after Qt has been built.
I happend to have a small example here that uses ExternalProject_Add to build a library followed by an application. In that example, CMake for the library and the application is invokved at make time.
cmake_minimum_required(VERSION 3.0)
include(ExternalProject)
ExternalProject_Add(cmake_lib
URL ../cmake_lib
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
)
ExternalProject_Add(cmake_app
DEPENDS cmake_lib
URL ../cmake_app
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
)
The problem with Qt 5 is that it doesn't use cmake to get built, and thus your ninja build process won't know anything about the internals of Qt unless you tell it everything. E.g. if you change any dependencies of Qt, or if Qt gets partially built, you'd have to add a lot of knowledge to your project's build system to determine whether the Qt build needs to be invoked again. This can be certainly made to work in a "fire and forget" style of build, where the build always starts from scratch, like in a CI system. One quickly runs into serious trouble if the intent is to change Qt itself and re-run the build. Even Qt's own build system has serious trouble with full dependency tracking due to fundamental architectural decisions in qmake.
Qmake-based developer re-builds of Qt suck - and they do to such an extent that I didn't bother contributing to the project since it felt like a penance, where the simplest of changes to one source file would take a minute or more to rebuild on, and any changes to qmake project files would sometimes ballon into multi-minute affairs.
The only solution that I have found that actually works and doesn't make you hate life, the universe and everything, was to reimplement Qt's build and configuration system using cmake, so that qmake becomes unnecessary. As a result, a statically linked unity debug build of qtbase takes a couple of minutes with all features enabled - it's pretty zippy and is much faster than the fastest option provided by Qt 5 on Windows for MSVC builds: qmake+jom.
The Qt project endeavored to do this during Qt 6 development, and I believe that they were successful :)

QT5.0.2 project needs more DLLs than QT4.8

Recently we moved to QT 5.0.2 from QT4.8. Our project now needs more DLL files than the earlier. It requires qml, opengl, printer modules. However we did not use any of these modules in our application. The size of exe file increased due to additional DLLs.
QT-= qml opengl -> did not exclude this module from our application.
Are these additional DLLs are compulsory for Qt 5.0.2 ? Is there any way to come out from this? We need to exclude these dlls to reduce exe size.
Some of the modules you use may be dependent on those you don't, which means your project depends on them indirectly. For example, by default, some modules (QtWebKit, QtMultimedia) utilize ANGLE which uses OpenGL. You can try to trace those dependencies by using a program named Dependency Walker (available here). The Qt GUI has changed a lot since 4.8, and there are now separate modules for printing and other functions (see here).
Sources:
Qt 5 on Windows ANGLE and OpenGL
Qt 5 Deployment on Windows
By the way, someone has (had) a similar problem: http://www.qtcentre.org/archive/index.php/t-52102.html. (Unfortunately, there is no solution in that link.)
It turned out that this is actually a bug in Qt.

Does Qt creator by default statically or dynamically link it's libraries?

I'm developing a closed source application and to do so in accordance with the LGPL I have to dynamically link Qt's libraries to my application. Does Qt do this by default or do I have to take steps to do so? If that's the case how would I go about doing it?
Qt uses dynamic linking by default.
You'll notice this immediately during deployment to a non-developer machine, because your code will not run without the Qt libraries.
If your concern is the LGPL, just be careful when compiling Qt itself. Most LGPL violations with Qt are not because of static linking (since dynamic is the default), but for compiling Qt with non-default parameters.
LGPL is not just that the library must be provided along your binaries, but also that you specify how your users can build themselves the LGPL part. If you compile Qt yourself and do not use the pre-compiled binaries from the website, you must document that part of your build configuration in your release!
As soon as you get something running on your program, start preparing a release version for a non-developer environment without Qt installed. Your program should fail as soon as you delete the DLLs that you must copy along your program (or whatever format your OS uses).
It does it by default, statically linking seems to be quite involved judging by the many questions on the site regarding it.

Very large .app bundle created when deploying Qt app on OS X

I have been using Qt for a while on Linux and Windows. However, yesterday I picked up a new MacBook Pro so naturally I've been playing around to see if I could build my Qt apps on Mac.
I got pretty much everything working, however there is one problem : the file size of the resulting app bundle.
I am building my application like this:
qmake -spec macx-g++
make
macdeployqt my.app -no-plugins -dmg
The bundle and everything seem to work fine, but, the generated .app is 31.1 MB large and the .dmg is 13.6 MB!
Is this normal? Can I reduce this horrible size (on Windows, my installer for the same app with all the libraries is ~4 MB)?
If you are using the pre-built Qt libraries then the chances are that they are universal binaries with multiple architectures. For example, do $ file my.app/Resources/Frameworks/QtCore.framework/Versions/4/QtCore and you will see multiple architectures.
You can build your own Qt libraries with only the architectures that you want to support. You may wish to not support PPC because that is ancient; or if you are using a current Qt then you can make the decision of 32 bit vs 64 bit, but that's another question.
The problem is the size of the Qt dynamic libraries, as they must be part of your bundle.
These sizes can usually be reduced.
See the solution of How do I make apps smaller with qmake and macdeployqt on how to do this.
An excellent workaround would be a static build of Qt and linking your application against the static build. This usually is a very good idea as two applications installing Qt dynamically usually crash on Mac OS.
Your application will have with static build (from my exp.) approx. 10-20MB of size. Combined with the steps above, some more reduction might be possible.

How to build QTcore4.dll without dependency to MSVCx80.dll?

I have a windows screensaver that I want to recompile using the QT libraries, so that I can make available for more platforms.
I am facing problems with the deployment on Vista and XP.
I compile my screensaver statically with MT, and run the dependency checker.
The results are:
MyScreensaver.SCR needs several DLLS, QTCORE4.DLL but no MSVCx80.DLLs.
So far this is fine.
My problem is that QTCORE4.DLL in its turn, does need MSVCP80.DLL and MSVCR80.DLL
As a result my application does not run on Vista systems.
Can I build QTCORE4.DLL to be statically linked the the microsoft libraries (maybe Libcmt.lib ?) so that I do not have any dependencies in the MS CRT DLLs?
Limitations:
I do not want to have the users install the MS VC redistributables. The screensaver is only 1 MB, and it is ridiculus to ask the user to do so many changes in his computer just for a screensaver.
I do not want to use the trick to put the MS CRT dlls in the same application path with the screensaver because screensavers are installed in system32, and I want to install the minimum possible files there.
Finally, I do prefer to produce a monolithic program, rather that a bunch of DLLs
I tried a full static compilation and link of QT, but this is not allowed (if I understood correctly, by the LGPL) and also it is not recommended according to this: http://www.qtsoftware.com/developer/faqs/why-does-a-statically-built-qt-use-the-dynamic-visual-studio-runtime-libraries-do-i-need-to-deploy-those-with-my-application
After trying for solutions in various directions, it seems the most feasible one is to use the QTCore4.dll and QTGui4.dll, but having them linked statically to MSVCRT. In this way, neither my program, nor the QT DLLs will have dependencies on MSVCRT dlls.
Is there a solution to this?
( I am new to QT programming )
Thank you,
Michael
I think they are concerted that parts of your application will be compiled with /MD(d) and parts with /MT(d), but if you control everything (including 3rd party libraries) then its pretty safe to use /MT(d).
You have two options:
Those dependencies are part of Microsoft Visual C++ Runtime Library, you can deploy that library in your installshield and user silently installs it, MSVCRT library not included in Windows by default, you must deploy runtime library in your installshield and copy Qt*.dll DLLs in your application directory.
Use Static Linking of Runtime and Qt main dependencies, with this option you have one executable file, but to static compile of Qt you must have Qt commercial License for commercial use.

Resources