Deploying Qt or how to avoid “could not find or load the Qt platform plugin”
(转自:http://www.tripleboot.org/?p=138)
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, instead you’re stuck on errors like these?
If you’ve experienced this, then this blog post is for you :-)
(Start your app in Terminal to see this)
(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 rebuild
all or parts of Qt statically. In some environments that makes sense,
but I think in general you’re better off following this dynamic library
approach.
(Updated November 16, 2014 for Qt 5.4)
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.4.0 it will prompt you with
something like C:\Qt\Qt5.4.0
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.4 it’s 5.4
; it contains a subdirectory named after the compiler you selected, like clang_64, gcc_64, mingw482_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.
Also: apps compiled in release mode with the MingGW compiler for
Windows, actually will tell you more than when they’re compiled in debug
mode, for example that message about not finding the Qt platform plugin
which this blog post is all about, will only be displayed in release
mode.
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 that has no Qt installed.
Depending on your OS and compiler, the files you then need to copy vary
slightly:
Windows compilers:
(update Nov. 16 2014: What about Visual Studio 2015, does it work with Qt? Haven’t tested yet, but I’m guessing it will do just fine)
(note: the screen dumps are still from Qt 5.3, not yet from Qt 5.4,
so the icu*.dlls should instead be icudt53.dll etc. But you’ll get the
idea anyway I think…)MinGW 32-bit compiler
Bare bones MinGW deployment
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.4\mingw482_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 32-bit and 64-bit deployment
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 filesmsvcr120.dll
andmsvcp120.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 aC:\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
andmsvcp120.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 copiedmsvcr120.dll
and/ormsvcp120.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:
Bare bones VS2013 OpenGL 32-bit and 64-bit deployment
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
andlibGLESv2.dll
dependencies. So theqwindows.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 filesmsvcr120.dll
andmsvcp120.dll
.
Visual Studio 2012 32-bit OpenGL compiler:
Bare bones VS2012 32-bit OpenGL deployment
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 aremsvcr110.dll
andmsvcp110.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 insteadmsvcr100.dll
andmsvcp100.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, 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 thebin
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:
(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 preferQMAKE_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. Note that those .so files are loaded by Qt itself and not
by Linux (more on that in an upcoming blog post), so I suspect the RPATH
setting is irrelevant anyway. Matter of fact, I tested this:cd platforms
chrpath -r grapefruit libqxcb.soHelloQt started fine in spite of not having any grapefruit directory
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 applyingchrpath
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 (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
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
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
Now, if you copy this 20MB bundle to another Mac, it should run just fine.
macdeployqt
does a lot ofinstall_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
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.
Deploying Qt or how to avoid “could not find or load the Qt platform plugin”的更多相关文章
- qt打包问题。启动失败:Application failed to start because platform plugin “windows” is missing
qt打包启动失败:Application failed to start because platform plugin “windows” is missing 通常的原因是因为没有platform ...
- This application failed to start because it could not find or load the Qt platform plugin "xcb".
1. copy libQt5DBus.so.5 2. add QT_PLUGIN_PATH blog.csdn.net/windows_nt/article/details/242 ...
- This application failed to start because it could not find or load the Qt platform plugin "xcb".
linux根据系统Qt5未安装编译的程序Qt在该系统下进行下面的错误会报: This application failed to start because it could not find or ...
- 解决Qt编译动态链接库could not find or load the Qt platform plugin "windows" in.问题
最近用Qt5做了一个项目的界面,在编译成可执行文件EXE之后,运行文件,提示: This application failed to start because it could not find o ...
- Qt-c++桌面编程报错:qt.qpa.plugin: Could not find the Qt platform plugin "windows" in "",已解决
语言:c++ 编译库:Qt GUI,qt5.12.1 软件类型:Qt application,qt桌面软件 运行平台:window 10 ?按照[https://www.devbean.net/201 ...
- QT移植无法启动 This application failed to start because it could not find or load the QT platform
QT配置好在自己机器上可以运行,但在别人机器上一直弹出 "This application failed to start because it could not find or load ...
- QT 编译遇到重定义;不同的基类型&在QT中使用C++ lib库
最近在使用osg和qt开发,在集成osg时候因为我使用的qt版本为非opengl的版本,导致qt自己封了一遍opengl的一些基类变量如double 这时候就会跟osg中声明的opengl的类型冲突, ...
- TensorFlow: Could not load requested Qt binding.
使用Eclipse 引入tensorflow,出现 Could not load requested Qt binding. 问题 ImportError: Could not load reque ...
- Qt::WindowFlags枚举类型(Qt::Widget是独立窗口和子窗口两用的,Qt::Window会有标题栏)
Qt::Widget : QWidget构造函数的默认值,如新的窗口部件没有父窗口部件,则它是一个独立的窗口,否则就是一个子窗口部件. Qt::Window : 无论是否有父窗口部件,新窗口部件都是一 ...
随机推荐
- Python开发【Django】:Model操作(一)
Django ORM基本配置 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接数据库,并编写数据访问层代码 业务逻辑层去 ...
- linux 的nohup & 和daemon 总结(转)
add by zhj:守护进程貌似跟nohup + &方式启动的进程差不多.都可以实现与终端的无关联. 原文:http://blog.csdn.net/lovemdx/article/de ...
- 爬虫之selenium使用
详细使用链接: 点击链接 selenium介绍: selenium最初是一个自动化测试工具,而爬虫中使用它主要是为了解决requests无法直接执行JavaScript代码的问题 selenium本质 ...
- nginx lua模块安装
1.安装LuaJIT,LuaJIT为LuaJIT is a Just-In-Time Compiler (JIT) for the Lua programming language wget http ...
- atime、mtime、ctime的区别及如何降低atime更新 mount时的option noatime
atime.mtime.ctime的区别及如何降低atime更新 mount时的option noatime http://mp.weixin.qq.com/s?__biz=MzA3MzYwNjQ3 ...
- ubuntu 用法
1:改变某一个目录的拥有者 sudo chown -hR user:user ./目录名 // user:user 用户名:组名 sudo chmod 777 文件 //给文 ...
- 【原创】PHPstorm本地修改同步保存到远程服务器
PHPstorm设置本地修改的代码同步保存到远程服务器: 设置里面搜索“Deployment”,选择+号,然后选择SFTP: 填写远程主机的信息: 然后选择Mappings,填写本地代码路径和远程主机 ...
- 2006 - MySQL server has gone away
mysql出现ERROR : (2006, 'MySQL server has gone away') 的问题意思就是指client和MySQL server之间的链接断开了. 造成这样的原因一般是s ...
- 【转】Deep Learning(深度学习)学习笔记整理系列之(二)
因为我们要学习的是特征的表达,那么关于特征,或者说关于这个层级特征,我们需要了解地更深入点.所以在说Deep Learning之前,我们有必要再啰嗦下特征(呵呵,实际上是看到那么好的对特征的解释,不放 ...
- 一个很大的文件,存放了10G个整数的乱序数列,如何用程序找出中位数。
一.梳理审题 一.看清题目: 注意这个题目的量词,这个文件中有10G个整数,而不是这个文件占了10G的内存空间. 二.一些疑问: 在计算机中我们讲的G.M等都是存储容量的概念,但是一般都会在会面加上B ...