Back to Blog home

So I wrote this application and want my users to run it, what now?

Published on Tuesday February 05, 2008 by Gunnar Sletta in Qt Qt Jambi | Comments

I planned on writing a blog about some of the work we've done on deployment for Qt Jambi 4.4, but I realized when writing that the memory of "Why the !"#!%!§ doesn't it work on that linux box!" was still to fresh in memory and I was simply to upset to write anything about it. Some time has passed and a Finnish company came along, putting things into perspective, so now I can calmly share some thoughts on deployment with you...

Deploying C++ software across multiple platforms can be rather painful, partially because Qt doesn't really provide any tools to help out. We do provide deployment guides for the various systems, but our users still have to learn and understand all the details. It doesn't "just work". Why? you may ask...

On windows life used to be pretty simple, you ship your .exe and .dll's together in the same directory together with the right runtime libraries and you're set, alternatively build with Visual Studio 6.0 and almost don't worry about it at all. This was until a certain company introduced manifests as a way of describing dependencies between libraries and executables. It does sound great on paper, but in practice it really doesn't work, especially if the executable (java.exe in this case) is built without manifest. As a direct effect, you are now required to either preinstall the runtime libraries in the WinSxS folder (via installer) or duplicate the runtime libraries in all directories that contain executable code, such as /lib, /bin and /plugins/..., meaning that each plugin directory needs to have its own duplicate copy of the MS runtime libraries. Should you choose to not follow these rules, the application won't run...

On Linux we have the problem that the various systems are vastly different. Some boxes didn't have Xinerama installed, some have libstdc++ version 5, some have version 6. Some have Qt installed with debug symbols and some have Qt 3 installed. Basically there are a lot of variables and the only way to go about this is for our users to ship a complete bundle containing all dependencies. In Qt 4.4 we changed Qt in some places to support dynamic resolving and loading a few X libs which reduced the dependency table a bit. In Qt 4.3 our binaries were built without Xinerama for instance, to make them run on certain systems. Since Qt 4.4 we support Xinerama if its available on the deployment machine out of the box.

On Mac OS X, things are immediately rather bright, save for this minor issue of install_name... Install names describes, among other things, the location of dependent binaries. When build Qt libraries in the default way, the dependencies will be absolute file names to things like ~/qt/lib/libQtCore which doesn't work on a target machine. In Qt 4.3, we patched our prebuilt binaries to contain relative paths to where they were loaded from, but our users who built Qt Jambi themselves would have to do this too, which is a rather messy process. Why not simply use frameworks or bundles, and the reason is simply that we want to have a means of deployment that feels java-like and works identically across all platforms, so our users can understand this, and not care anymore about deployment on any target system. Frameworks and bundles are pretty far from that...

In addition to these platform spesific problems, we have the issue that in Java, you normally relate to .jar files which are portable while native libraries, such as the Qt C++ libraries, have to be available on the file system for the application to load them. These native libraries need to be available through the java.library.path, which equals the environment variables PATH on windows, LD_LIBRARY_PATH on Linux / UNIX and DYLD_LIBRARY_PATH on OS X. In Qt Jambi 4.3 we did provide some magic to automatically find the libraries without the environment variables, but ideally you want to relate to just .jar files, right? Well... With Qt Jambi 4.4 you can!

What we ended up doing is that we created some ant tasks to help us and our users out. The way it works is that we have build tasks for running qmake, make and juic and a task for bundling. The bundle task will make sure the binaries have the right install name in place on Mac OS X and on windows it will copy the manifests and runtimes into the right subdirectories. The result of this is a .jar file, for instance qtjambi-win64-msvc2005-4.4.0_01.jar which contains the correct native binaries for Windows 64bit and when its in the classpath, it will just work. Similarly it will create a qtjambi-linux32-gcc-4.4.0_01.jar for linux, and if you put both the two in the classpath, it will pick the right one.

This makes it extremly easy for the people that deploy a plain Qt Jambi application, as they simply include a .jar file in their classpath and it works. The slightly more complex scenario is where you generate some code using the Qt Jambi Generator and want to deploy that. The process is rather similar, you simply add your binaries to the bundle task and you get a .jar file containing Qt Jambi native libraries and you own native libraries and once again you are set. We still support loading binaries from the environment variables listed above, which is handy for development and for starting Qt Jambi from a C++ app, like Qt Designer, so hopefully, we covered most scenarios.

We hope to have the Qt Jambi 4.4.0_01 Beta out by the end of february, so I'm looking forward to getting your feedback on this...

Subscribe to Our Blog

Stay up to date with the latest marketing, sales and service tips and news.

We are updating our comment system and you could face some issues. Please write to us at feedback@qt.io to report issues/bugs.