Deploying Qt or how to avoid “could not find or load the Qt platform plugin”

Once you’ve built your first Qt program, have you tried it on another PC?
(Post updated and simplified! Thanks to JKSH on the Qt Project forums.)
Maybe you’ve gotten past .DLL errors and instead got errors like this?

Could not find or load the Qt platform plugin "windows"

If you’ve experienced this, then this blog post is for you ๐Ÿ™‚

 
Failed to load platform plugin "xcb"

(Start your app in Terminal to see this)

Failed to load platform plugin "cocoa"

(Same here, Finder only says “App quit unexpectedly”, launch your app in Terminal to see this)

(Want to skip the tourist talk? Jump to the rest of the post.)

If you look at newer languages like Google’s Go, you’ll find an Everything and the Kitchen Sink™-flavored approach to deployment. After you’ve written and debugged a Go program, you issue the go build command. The result is an .EXE file with minimal dependencies on the DLLs, in Windows for example it’s just the usual suspects like KERNEL32.DLL etc. People sometimes complain though, because even a simple ‘Hello World’ app weighs in to an approx. 2MB .exe file. But deployment problems are more or less nonexistent.

Qt has (as you’ve probably discovered) the complete opposite design. From things like .h files that are designed this way (a humongous file like Windows.h is frowned upon) to the delegation of .DLLs that Qt uses for plugins, platform independency etc. Partially this stems from the early 90’s when Qt was initially designed (in those days, deploying a 2MB .exe could constitute a career-limiting move) but probably mostly because it supports so many different architectures and OS’es.

Now, to simplify deployment of Qt apps to other PCs, you can build your app together with Qt statically. For example, the MaintenanceTool app included in your Qt’s root directory is built that way (as well as Qt’s online/offline installer programs). In some environments that makes sense or is required (like when deplyoing Qt apps to iOS/iPhone) but let’s begin with the simple version: distributing Qt using DLLs/shared files.


First let’s look at the stuff you get when you download and install Qt. You can use the online or the offline installer. To simplify this blog post, let’s focus on the online installer. It will prompt you for the main Qt install directory, the default is ~/Qt for Mac and Linux and C:\Qt for Windows systems. The offline installer instead will default to a version specific directory, for Qt 5.5.1 it will prompt you with something like C:\Qt\Qt5.5 for MinGW on Windows. The files installed will be the same anyway, let’s assume you go with the online installer and accept the default directory name Qt. Inside that directory will be a couple of subdirectories, like Examples, Docs and Licenses. On Windows and Linux there will be a subdirectory called Tools which contains Qt Creator, Qt’s IDE (on the Mac there is no Tools subdirectory, instead there’s a Qt Creator.app).

Important: that Tools subdirectory contains a version of Qt deployed for Qt Creator; copying those files from the Tools directory will give you Bad Karma because they are customized for Qt Creator and *not* for your apps. Instead, look in the other directory created, for Qt 5.5.1 it’s 5.5; it contains a subdirectory named after the compiler you selected, like clang_64, gcc_64, mingw492_32, msvc2013 etc., that’s where you’ll find the compiler specific Qt files which can be distributed safely to other computers. I’ll be referring to that one as the compiler directory in this blog post. (And inside it are the important bin, lib and plugins subdirectories, more on that later.)

So let’s start by looking at deployment of an absolute bare bones app, let’s call it HelloQt. In Qt Creator, select a new Project, Applications and a Qt Widgets application. Click through and accept all the default choices. Once you’re in the project, switch it to Release mode. This is to simplify deployment, and if you’re using Visual Studio as your compiler, Microsoft disallows copying any of the debug .DLLs to another computer.

Right now don’t edit or add any code, for our purposes an empty app window will do just fine. Just build our fancy app in Qt Creator, then make a test directory on another computer without any Qt installed. Depending on your OS and compiler, the files you then need to copy vary slightly:

  • Windows:

    • MinGW 32-bit compiler

      Bare bones MinGW deployment

      Bare bones MinGW deployment

      Bare bones MinGW platforms directory

      Bare bones MinGW platforms directory


      The qwindows.dll file in the platforms directory above, you’ll find and can copy from compiler directory\plugins\platforms, the other files you’ll find in compiler directory\bin.

      (What’s that compiler directory you ask? Look in the text above for an explanation. For MinGW installed with the online installer the default directory is C:\Qt\5.5\mingw492_32)

      The HelloQt app should now run fine on the other Windows computer.
       

    • Visual Studio 2013 32-bit and 64-bit compilers:

      Bare bones VS2013 64-bit deployment

      Bare bones VS2013 32-bit and 64-bit deployment

       
      Bare bones VS2013 platforms directory

      Bare bones 32-bit and 64-bit platforms directory

      The qwindows.dll file is in compiler directory\plugins\platforms and the other files you’ll find in compiler directory\bin. Let’s not forget the 2 compiler specific files msvcr120.dll and msvcp120.dll, I usually copy them from C:\Windows\SysWOW64 on my development PC.

      For 64-bit app deployment the file setup above is identical, but beware: the 2 compiler files msvcr120.dll and msvcp120.dll you instead find in C:\Windows\System32. The HelloQt app should now run equally well on the other computer.

      Again: note that the 32-bit MSVC DLL files are in SysWOW64 and the 64-bit files are in System32. Makes perfect sense, agreed?

      (update Nov. 16, 2014:) Q: “No, it does not make perfect sense, please enlighten me, o great guru”
      <history_rant> In the beginning there was Windows 1.0, it had a C:\Windows directory, inside it was a System subdirectory and there was much rejoicing. Then a software called Chicago a.k.a. Windows 95 was released upon the world. It supported 32-bit Windows apps, those apps required 32-bit flavored infrastructure like DLLs and drivers, and some of those files were identically named as their 16-bit siblings. Solution: put those files in another System subdirectory and call that (surprise!) System32. All was well again and rejoicing resumed.
      A new century and 64-bit computing arrived. The naive among us expected the creation of a 3rd subdirectory called System64, for housing the new fancy 64-bit Windows infrastructure. But alas, it was not to be ๐Ÿ™ Because a fear had spread upon the land, a fear that System32 had become too popular and too ingrained. The belief was that the necessary migration to System64 would cause intolerable pain and suffering and perhaps taint the perceived quality of the Windows product. Succumbing to this fear, it was decided that for all 64-bit Windows releases, System32 was to be the home for the 64-bit infrastructure and the old (32-bit) content of System32 was instead to be ignominiously shuffled away into a new subdirectory called SysWOW64. Thus, it was believed, 64-bit Windows should be able to accommodate even those developers that wanted to ascend to 64-bit computing but had fumbled and put hardwired strings like “System32” into their apps. (BTW, a similar kind of decision was also taken for C:\Program Files, so that it would contain the 64-bit apps and 32-bit apps would instead be stored in C:\Program Files (x86).) And that’s the story how we ended up with 32-bit DLLs in SysWOW64 and 64-bit DLLs in System32.
      Today, more than 10 years later, I think giving in to that fear was a humongous mistake. Until all 32-bit Windows installations are gone, every day some developer will have to think and spend extra time deciding which directory is correct for picking up the compiler files and similar stuff. If a System64 directory had been created there would be less confusion. </history_rant>

      Q: “I copied the msvcr120.dll and msvcp120.dll files as you said, why do I get error 0xc000007b when I try to launch my app on the other computer?”
      This error occurs when a 64-bit app requests a DLL and a 32-bit version of it is incorrectly loaded, or the other way around, i.e. a 32-bit app loads by mistake a 64-bit DLL. Usually this is because you copied msvcr120.dll and/or msvcp120.dll from the wrong directory (either C:\Windows\System32 or C:\Windows\SysWOW64, also see my rant above).

      Q: “I copied everything ok, but when I try to launch I get a dialog box: “not a valid Win32 application” why?”
      If the other computer has Windows XP or Windows Server 2003 you’ll get this error. To get around it, you need to add a linker setting for your project in Qt Creator, I’ll show you how in the next blog post about XP/2k3 deployment.
       

    • Visual Studio 2013 32-bit and 64-bit OpenGL compilers:

      MSVC 2013 OpenGL barebones deployment

      Bare bones VS2013 OpenGL 32-bit and 64-bit deployment

       
      MSVC 2013 OpenGL barebones deployment platforms directory

      Bare bones VS2013 OpenGL 32-bit and 64-bit platform directory

      This deployment is almost identical to the non-OpenGL versions above, but slightly easier since there are no libEGL.dll and libGLESv2.dll dependencies. So the qwindows.dll file is in compiler directory\plugins\platforms and the other files you’ll find in compiler directory\bin. And don’t forget the two compiler specific files msvcr120.dll and msvcp120.dll.
       

    • Visual Studio 2012 32-bit OpenGL compiler:

      Bare bones VS2012 32-bit OpenGL deployment

      Bare bones VS2012 32-bit OpenGL deployment

       
      Bare bones VS2012 32-bit OpenGL platform directory

      Bare bones VS2012 32-bit OpenGL platform directory

      The qwindows.dll file is in compiler directory\plugins\platforms and the other files you’ll find in compiler directory\bin. Note that the two compiler specific files in this case are msvcr110.dll and msvcp110.dll.
       

    • Visual Studio 2010 32-bit compiler:

      I have to confess to some laziness here, I haven’t tried recently with VS2010. But it should be the almost exactly as the VS2012 deployment above, except that the compiler specific DLLs are instead msvcr100.dll and msvcp100.dll. Good news: deploying apps built with this compiler to Windows XP or Windows Server 2003 presents no problems.
       

  • Linux GCC 32-bit and 64-bit compilers:

    Debian/Ubuntu GCC bare bones deployment files

    Debian/Ubuntu GCC bare bones deployment files


    Debian/Ubuntu GCC bare bones deployment, platform directory

    Debian/Ubuntu GCC bare bones deployment, platform directory


    Here the platform file is called libqxcb.so, it can be found in compiler directory/plugins/platforms. The other files are in the compiler directory/lib directory (note: not the bin directory as on Windows above). There are no compiler specific .so files, it’s assumed the Linux system you’re targeting is up to scratch re. the libc.so, libgcc_s.so etc files. I suppose if the other Linux is really old this could be a showstopper, I haven’t looked into that possible malaise yet.

    Note that the .so files in the /lib subdirectories are installed by the Qt installer in 4 incarnations: 3 symbolic links and 1 real McCoy, e.g. libQt5Core.so, libQt5Core.so.5 and libQt5Core.so.5.4 are symbolic links to the “real” file libQt5Core.so.5.4.0.
    However, when you list HelloQt’s DLL dependencies, for example typing "ldd HelloQt" in Terminal, you’ll see that the requested .so files are suffixed with just .5, when I copy the files I also rename the real McCoy file from xxx.5.4.0 to xxx.5 and toss the 3 symbolic chaps. (That’s why it’s only one of each above in the screen dumps.) This keeps the no. of files down, also sometimes symbolic links can become roadkill during transit, if you’re zipping them or copying via SMB to a Windows server etc. But you can of course equally well go ahead and copy all 4 of them.

    Update: in Qt 5.4, I noticed that the 3 libicu*.so Unicode files now are installed in 2 incarnations, one *.so.53 which is the symbolic link (the one HelloQt looks for) and the *.so.53.1 which is the real thing. So we’re applying the same algorithm here, copied and renamed the 3 real files and skipped the symbolic links.

     
    When you copy the files shown above to another Linux computer, if you try to launch the HelloQt app you’ll most likely get this error:
    Forgot chrpath

    (On Ubuntu systems the app might run anyway because a fairly recent Qt is included in their distro, more on that below.)
    The reason for this is that the .exe/ELF file is built to look for Qt’s .so files assuming the same library path to them as on your development machine. Even though we’ve copied all the needed .so files (and the platform subdirectory) into the same directory as our app .exe/ELF file, those .so files are ignored in Linux. But we would like to have the same behavior as on Windows; i.e. that Linux when loading the .so files also looks for them in the same directory as the .exe/ELF file is in.
    There is a way to accomplish this, by editing that pre-wired path setting, actually it’s called the RPATH setting and you can choose to make that change either A) when building the app or B) as a command in Terminal after the build (or on existing .exe/ELF files).

    A) When building the the app: Qt (actually the linker) normally sets the RPATH just pointing to the .so files where Qt’s installer put them (for example in my case /home/henry/Qt/5.4/gcc_64/lib) which of course is fine and dandy for your development machine but less so for the other Linux PC.
    However we can tweak that setting by adding a line to our project’s .pro file (I usually put it at the end of my .pro file):

    QMAKE_LFLAGS += -Wl,-rpath,"'\$$ORIGIN'"

    What we want is to insert the magic word $ORIGIN as the first RPATH setting, this will cause Linux to look for .so files to load in the same directory as the .exe/ELF file. (The extra decoration "'\$...'" is needed for surviving the heavy munging during the build process before arriving at the linker.)
    Actually we can equally well use “.” as an RPATH (i.e. QMAKE_LFLAGS += -Wl,-rpath,"." this will perform the same feat as $ORIGIN) but the docs advise us to use $ORIGIN, so $ORIGIN it is.
    (Note: there are a couple of other .pro file flag commands available for this, for example: QMAKE_RPATHDIR += ":'\$$ORIGIN'" but I prefer QMAKE_LFLAGS += ... because it causes $ORIGIN to appear as the first RPATH.)

    B) A command in Terminal: in typical Linux fashion there’s also a utility for setting RPATHs: chrpath, which you can install and run like this:

    sudo apt-get install chrpath
    chrpath -r \$ORIGIN HelloQt
    

    (replace apt-get with the download command of your favorite distro if needed)

    The $ORIGIN (\ is needed for quoting the $) keyword means the same as above: look for .so files in the same directory first, in other words, emulate Windows .DLL lookup behavior. Also here you can use "chrpath -r . HelloQt" but the docs (as I mentioned above) advises against it.

    Note: we only need to apply chrpath on our main .exe/ELF file, Qt’s .so files already have their RPATHs set to $ORIGIN, i.e. they expect to find each other in the same directory.

    BTW, you don’t need to install chrpath on the other PC, you can do that on your development machine, i.e. prepare the .elf file before shipping (unless of course you instead opted for that extra QMAKE_LFLAGS… line in your .pro file).

    Q: “Not correct, Qt plugins/platforms .so files have their RPATHs set to $ORIGIN/../../lib, not just only $ORIGIN”
    Indeed I’ve seen that, while the .so files in the Qt’s lib directory have $ORIGIN, all the .so files in the plugins directory are wired differently. Starting with Qt 5.5 these plugin .so files are loaded similarly as the other Qt .so files, which means you either have to change their RPATHS or make sure they are placed so that $ORIGIN/../../lib points to your normal Qt .so files. Note: I’ll be updating/expanding on this new problem soon in this blogpost, sorry for my laziness!

    Q: “But on my Ubuntu machine HelloQt runs anyway, don’t need chrpath!”
    Yes, that’s because Ubuntu comes pre-installed with Qt library files. For example, Ubuntu 13.10 comes with Qt 5.0.2. It’s pretty neat but comes with one danger: what happens if you rely on a Qt feature that was introduced after 5.0.2, like SerialPort? You’ll get an error: “libQt5SerialPort.so.5” not found, even if you do copy that .so file from your Qt machine. To refrain from diving into one of Dante’s nine “DLL Hells”, I suggest always stick to the plan of applying chrpath to your apps.

    Update: User sunsina on the Qt Project forums suggested a more sophisticated deployment approach: put the Qt’s .so files in a subdirectory called qtlibs:
    (Note: picture isn’t updated yet to Qt version 5.4)

    Debian alternate Qt installation

    Debian (or Ubuntu) alternate Qt installation


    To get this setup up and running, we just need to apply a different chrpath setting to our .elf file:

    chrpath -r ./qtlibs HelloQt
    

    It’s a good point, just because Windows looks for DLLs in the current directory by default, that doesn’t mean we have to go for the same approach here.
     

  • Mac clang compiler:

    The algorithm we’ve used above for Windows and Linux, to copy the executable file and the needed .dlls together and making sure no mixing of 32 and 64-bit flavored files occurs; on the Mac that’s regarded as a clueless all thumbs approach to app deployment. To paraphrase Obi-Wan speaking about his light saber: “not as clumsy or random as a simple app directory, the app bundle is an elegant weapon for a more civilized age.” And it’s hard to argue, the app bundle is a great invention, installing and uninstalling apps couldn’t be simpler.

    So, when you build your app with QtCreator you’ll get an app bundle, do a “Show Package Contents” in Finder, open the Contents folder to see the bundle in all its glory:

    App contents before macdeployqt

    App contents before macdeployqt

    Now, if you copy the app bundle (HelloQt.app) to another Mac and try to launch it, it will fail. Right now it’s mostly an empty shell, none of Qt’s DLLs (frameworks and dylibs) are present. The executable file, for example, is set to load QtCore.framework and the other frameworks from where you installed Qt.
    So while the app bundle is fine and dandy on your development machine, it clearly needs some more stuffing before you can deploy it to another Mac. I used to do this manually until I read on Qt’s website about a handy utility included in Qt’s installation that helps you with this, it’s called macdeployqt. You can find it in your ../clang_64/bin directory.
    Here’s an example, we’ll run it on our HelloQt app, using Terminal:

    Using macdeployqt from Terminal

    Using macdeployqt from Terminal

    It’s designed according to the paradigm “no news is good news”, i.e. if you don’t see any error messages, it all went well and the size of your app bundle should have grown. In the case of the HelloQt app from about 100 kbytes to 20 MBytes. Let’s open the Contents folder again:

    App contents after macdeployqt

    App contents after macdeployqt

    Now, if you copy this 20MB bundle to another Mac, it should run just fine. macdeployqt does a lot of install_name_tool invocations and other shuffling that (believe me!) you should be very glad not to have to do yourself.

    For deployment problems, the first tool you need to learn on the Mac is otool (the devs who wrote it were watching Lawrence of Arabia with Peter O’Toole at the time, no just kidding!). Example: to see what .dylibs our app needs, do:
    otool -L .../HelloQt.app/Contents/MacOS/HelloQt

    Note: once you’ve run macdeployqt on your app bundle, don’t reopen that project in QtCreator!
    If you do, you’ll see these kind of messages when you build and launch your app again:

    QtCreator does *not* like projects that macdeployqt has visited

    QtCreator does *not* like projects that macdeployqt has visited

    The cure is easy: just delete the build folder (which contains the app bundle), then you can start working on your app in QtCreator again.
     

  • Android and iOS:

    Interesting new Qt platforms but I haven’t gone there yet! I’ll update this blog post when I do.

So far I’ve covered how to deploy a bare bones app. Once past this hurdle, deploying real apps that depend on Qt libraries like ODBC, MySql, Sensors, QtQuick etc. follows the same approach.

Next blog post: deploying to Windows XP and Windows Server 2003.

Update: now when you know a bit more on how to deploy Qt apps, I’ve written a blog post on why the deployment works the way I’ve written about above.

36 thoughts on “Deploying Qt or how to avoid “could not find or load the Qt platform plugin”

  1. Hi,

    I finished up a project for Uni yesterday evening and decided to test it on another computer before sending it off. Thank God I did!

    I’ve spent a few hours trying to solve this on my own with no success. Your, however, solution worked perfectly, thanks for the help!

  2. I’m brand new to Qt! Only have a little C++ programming under my belt. So, with that in mind, please answer my stupid question…(I’ve already looked on several sites without any luck) How do I switch from “Debug” To “Release” mode in Qt Creator (Ver-Qt5.3)? Found plenty of pros and cons for each, but no simple answer on how to just switch it! Thanks!
    Bob

    1. Disregard my last! I finally stumbled across it in the “”PROJECTS” button. Now I just need to figure out why the Path Directory is in Red!!

  3. Ok,I’ve spent hours working on this and resolved several of the ME Caused problems. However, I got the program to Run as listed above and it worked on screen with a blank form. When I Build it, I get error saying Qt5Widgets.dll is not on my computer and to reinstall the program. (That .dll is in the 5.3 Bin folder.) I set the KIT to use Desktop Qt5.3.0 MSVS2013 OpenGL 64bit. The files do not look like those listed in the build here either. There is no “Platform” folder listed in the “HelloQt” root folder either. Please point me in the right direction!!

  4. Hi, the files I list above are from the 5.3 bin folder (for Windows versions), the platforms folder you’ll find inside the plugins folder, a neighbor to bin.

    Also note those files are what you’re supposed to copy to another computer without Qt on it. If you are working on a PC with Qt installed, there’s no need to copy anything ๐Ÿ™‚

  5. I’ve followed the tutorial as well as some additional steps found here:
    http://qt-project.org/forums/viewthread/22908

    However, I am getting an error exactly as this article depicts it, without any dll files in the error message when executing the release version of the built application, and an error related to QCore.dll similar to the one this article is about when executing the debug version of the built application.

  6. You are awsome!!!
    I’ve seen about 10 tutorials for QT linux deployment and only your’s worked perfectly, thank you so much!!

    Avi

    1. Hi, well it’s actually the truth, because Microsoft (about 10 years ago) decided to keep the name System32 for the new 64-bit flavored files, and instead store all the old 32-bit DLLs etc. in SysWOW64.

      I think instead they should have bitten the bullet and created a new System64 directory, but they didn’t. And I think reusing System32 this way is bad karma, hence my “makes perfect sense” ๐Ÿ™‚
      (a bit of rant, sorry!)

      Anyway, I should update this blog post and clarify this a bit more. Also I’ve seen people getting launch error 0xc000007b because they copied the wrong msvcr120.dll, i.e. 64-bit instead of 32-bit or vice versa, should document that as well…

  7. Thank so much for your post. It took me almost 4 days to get my first deploy work properly and only got when read your tips.

  8. Good summary post. One gotcha that wasn’t covered: If you delay instantiation of your QApplication, be sure to avoid Qt calls that are not explicitly permitted before QApplication is instantiated.

    I was getting this error message on deployment machines when we were accidentally calling QStyleFactory::keys() before the QApplication was instantiated. Moving that one call to after QApplication instantiation fixed our problems.

    1. Thank you! Thank you! Thank you!

      Your comment fixed my problem after I spend three days trying to figure it out.

      This should really be noted somewhere in Qt docs.

  9. You rock ๐Ÿ™‚ this is a great little guide in clear speak ๐Ÿ™‚
    Feeding this back into the Qt developers forums as they appear to have missed this simple solution to a common and otherwise elusive issue!

  10. Very good article. But it doesn’t work if your application includes Gui elements ( QML/Quick Control …) or WebEngine.

    1. Thanks! About QML etc.: indeed, when I wrote this post I didn’t know so much about QML or WebEngine, so I left them out. But now I’m working on my first QML app, so I intend to fix that ๐Ÿ™‚

  11. Why did you not use windeployqt tool? I am using that to generate install files but I get the same error. I have several version of Qt but I have added path to only Qt5.4 version to PATH variable so that it should ensure files are copied only from that folder but it’s not working.

    1. I did fix my problem, I was creating install and the subfolders were not getting copied due to install scrip, fixing that fixed the issue however still I am interested why you didn’t use windeployqt tool, it will make life totally simple. Thanks.

      1. Hi, good!
        About windeployqt: I tested it last year when I wrote this blog post, but at that time it didn’t properly deploy the MSVC runtime dlls and a SQL plugin dll. But I know it’s been improved, I will check it out…

  12. Hi!
    I’m deploying on linux, and copied the *so files, but when i run, the error segmentation fault happens. But my doubt is: How do i get and copy all the *so files that my app needs to a folder like qtlibs?
    Thanks

  13. Hi:
    Im using mingw 32 bits… i created the installer with inno setup, to compress all dll’s in an installer… However i get the error “could not find or load qt platform plugin windows”…
    I did coppy the qwindows.dll from the right folder (checked that many times). In my computer it works fine… but i still get the message in other pc.. any help please?

    1. Thanks, I know what you mean with “love Qt, hate Qt”. I’ve been lazy, need to update this for Qt 5.5. Good news is that the 5.5 release has simplified things slightly from a deployment point of view. Rgrds Henry

  14. Here’s a new twist: On a laptop running Windows 10, an existing installation of a Qt app (built with MSVC2013) stopped working, with that same error message about qwindows.dll. Of course Win10 is doing automatic updates all the time, but nothing in the app directories is shown as having changed.

Leave a Reply

Your email address will not be published. Required fields are marked *

Prove you're human * Time limit is exhausted. Please reload CAPTCHA.