Deploying Windows Applications: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
No edit summary
 
No edit summary
Line 1: Line 1:
=Deploying Windows Applications=
h1. Deploying Windows Applications


==What does that mean?==
[toc depth="2"]


In most cases the Qt applications you create don’t reside on your development machine just to please you. You want to distribute them and make them run without any further hazzle and dependency installations on any Windows machine: Copy, Double-Click and Run.
== What does that mean? ==


Normally Qt applications are compiled and linked against shared libraries (Windows: <span class="caps">DLL</span>=Dynamic Link Library, Unix: .so=Shared Object). When the compiled program is executed the code from the libraries needed is loaded at runtime. The point is now to know which libraries have to be shipped along with your application to make it run without having a full Qt installation on the target system.
In most cases the Qt applications you create don't reside on your development machine just to please you. You want to distribute them and make them run without any further hazzle and dependency installations on any Windows machine: Copy, Double-Click and Run.


==List of Libraries needed==
Normally Qt applications are compiled and linked against shared libraries (Windows: DLL=Dynamic Link Library, Unix: .so=Shared Object). When the compiled program is executed the code from the libraries needed is loaded at runtime. The point is now to know which libraries have to be shipped along with your application to make it run without having a full Qt installation on the target system.


Besides your compiled .exe file you need some libraries contained in the same directory as the executable.<br /> All needed libraries are located in your Qt installation bin directory, e.g. '''C:\Qt\5.4\mingw491_32\bin'''. If you have installed more than one development kits you need to copy the libraries from the correct kit of course.
== List of Libraries needed ==


'''<span class="caps">WARNING</span>: Don’t take the library files from the QtCreator directory which is compiled with <span class="caps">MSVC</span> and has slightly different entry points.'''
Besides your compiled .exe file you need some libraries contained in the same directory as the executable.<br />All needed libraries are located in your Qt installation bin directory, e.g. '''C:.4\mingw491_32\bin'''. If you have installed more than one development kits you need to copy the libraries from the correct kit of course.
 
'''WARNING: Don't take the library files from the QtCreator directory which is compiled with MSVC and has slightly different entry points.'''


In either case you need the following non-Qt libraries. The list was created from a Qt 5.4 installation:
In either case you need the following non-Qt libraries. The list was created from a Qt 5.4 installation:


{| class="infotable line"
{background:#009900;color:white}. |''. Library Name |''. Size |_. Remarks |<br />|&gt;. icudt53.dll | 21M | Unicode Lib |<br />|&gt;. icuin53.dll | 3.6M | Unicode Lib |<br />|&gt;. icuuc53.dll | 2.0M | Unicode Lib |<br />|&gt;. libgcc_s_dw2-1.dll | 118K | GCC Lib |<br />|&gt;. libstdc+''–6.dll | 1003K | Standard C''+ Library |<br />|&gt;. libwinpthread-1.dll | 48K | Pthreads for Windows |
|- style="background: #009900"
<font color="white">! Library Name
! Size
! Remarks
</font>|-
| style="text-align: right" | icudt53.dll
| 21M
| Unicode Lib
|-
| style="text-align: right" | icuin53.dll
| 3.6M
| Unicode Lib
|-
| style="text-align: right" | icuuc53.dll
| 2.0M
| Unicode Lib
|-
| style="text-align: right" | libgcc_s_dw2-1.dll
| 118K
| <span class="caps">GCC</span> Lib
|-
| style="text-align: right" | libstdc++-6.dll
| 1003K
| Standard C++ Library
|-
| style="text-align: right" | libwinpthread-1.dll
| 48K
| Pthreads for Windows
|}


Some might argue that there might arise a ''small problem'' with shipping '''27M''' <span class="caps">ICU</span> libraries. If you don’t need <span class="caps">ICU</span> (http://site.icu-project.org/) you need to recompile Qt with configure -without-icu.
Some might argue that there might arise a ''small problem'' with shipping '''27M''' ICU libraries. If you don't need ICU (http://site.icu-project.org/) you need to recompile Qt with configure -without-icu.


Next we need — depending on what your application needs — to copy the Qt <span class="caps">DLL</span>s. First have a look at your .pro file that has a line like:
Next we need — depending on what your application needs — to copy the Qt DLLs. First have a look at your .pro file that has a line like:


In this case you need to copy the following files:
<code>QT ''= widgets<code>
<br />In this case you need to copy the following files:
<br />{background:#009900;color:white}. |''. Library Name |''. Size |_. Remarks |<br />|&gt;. Qt5Core.dll | 4.7M | Qt Core classes — always needed! |<br />|&gt;. Qt5Gui.dll | 5.0M | Graphical User Interface Classes |<br />|&gt;. Qt5Widgets.dll | 6.2M | Widget Classes |
<br />So far for the core libraries to make the program run on other machines. But wait. Something important is missing:
<br />h2. Platform Plugins
<br />For some reason some vital functions for starting Windows applications are contained in '''qwindows.dll''' Located in '''C:.4\mingw491_32\plugins\platforms'''. Copying this file to the same directory to the other DLLs would not work. This file is expected in the '''platforms''' subdirectory:
<br /></code><br />.<br />├── Qt5Core.dll<br />├── Qt5Gui.dll<br />├── Qt5Sql.dll<br />├── Qt5Widgets.dll<br />├── icudt53.dll<br />├── icuin53.dll<br />├── icuuc53.dll<br />├── libgcc_s_dw2-1.dll<br />├── libstdc–6.dll<br />├── libwinpthread-1.dll<br />└── platforms<br />    └── qwindows.dll<br /><code>
<br />Now your application is good to go and able to run on other machines not having a fully blown Qt installation preinstalled. Unfortunately you still need to ship a total of approx. 45M (half without ICU).
<br />h2. Database Applications
<br />When shipping applications that need to establish a database connection you need to ship the '''Qt5Sql.dll''' and the database driver library you use to connect to the database. In this example we make use of SQLite:
<br /></code><br />.<br />├── Qt5Core.dll<br />├── Qt5Gui.dll<br />├── Qt5Widgets.dll<br />├── Qt5Sql.dll<br />├── icudt53.dll<br />├── icuin53.dll<br />├── icuuc53.dll<br />├── libgcc_s_dw2-1.dll<br />├── libstdc''+–6.dll<br />├── libwinpthread-1.dll<br />├── platforms<br />│   └── qwindows.dll<br />└── sqldrivers<br /> └── qsqlite.dll<br /><code>


{| class="infotable line"
You noticed that we created a sqldrivers directory holding the sqlite.dll copied from '''C:.4\mingw491_32\plugins\sqldrivers'''
|- style="background: #009900"
<font color="white">! Library Name
! Size
! Remarks
</font>|-
| style="text-align: right" | Qt5Core.dll
| 4.7M
| Qt Core classes — always needed!
|-
| style="text-align: right" | Qt5Gui.dll
| 5.0M
| Graphical User Interface Classes
|-
| style="text-align: right" | Qt5Widgets.dll
| 6.2M
| Widget Classes
|}


So far for the core libraries to make the program run on other machines. But wait. Something important is missing:
== Building a Windows Installer ==


==Platform Plugins==
First head over to http://download.qt.io/official_releases/qt-installer-framework/1.5.0/ and download the package for your operating system.


For some reason some vital functions for starting Windows applications are contained in '''qwindows.dll''' Located in '''C:\Qt\5.4\mingw491_32\plugins\platforms'''. Copying this file to the same directory to the other <span class="caps">DLL</span>s would not work. This file is expected in the '''platforms''' subdirectory:
After installation — we assume *c: — we need to create some files holding the installer meta data. I suggest creating a directory in your source root directory called &quot;installer&amp;quot; with this structure:


Now your application is good to go and able to run on other machines not having a fully blown Qt installation preinstalled. Unfortunately you still need to ship a total of approx. 45M (half without <span class="caps">ICU</span>).
</code><br />.<br />├── config<br />│   └── config.xml<br />└── packages<br /> └── my-package<br /> ├── data<br /> │ ├── my-executable.exe<br /> │ ├── …<br /> │ .<br /> └── meta<br /> ├── installshortcut.qs<br /> ├── license.txt<br /> └── package.xml<br /><code>


==Database Applications==
The installer can be instructed to install one or more '''packages'''. They are all located in the packages subdirectory. In the above example we have one package called '''my-package'''. In the meta directory we store the license, an installation script for the Windows Shortcut and a package.xml containing the meta data:


When shipping applications that need to establish a database connection you need to ship the '''Qt5Sql.dll''' and the database driver library you use to connect to the database. In this example we make use of <span class="caps">SQL</span>ite:
package.xml contains:


You noticed that we created a sqldrivers directory holding the sqlite.dll copied from '''C:\Qt\5.4\mingw491_32\plugins\sqldrivers'''
</code><br />&amp;lt;?xml version=&quot;1.0&amp;quot; encoding=&quot;UTF-8&amp;quot;?&amp;gt;<br />&lt;Package&amp;gt;<br /> &lt;DisplayName&amp;gt;Name of this Package&amp;lt;/DisplayName&amp;gt;<br /> &lt;Description&amp;gt;Short description&amp;lt;/Description&amp;gt;<br /> &lt;Version&amp;gt;1.0&amp;lt;/Version&amp;gt;<br /> &lt;ReleaseDate&amp;gt;2015-01-10&amp;lt;/ReleaseDate&amp;gt;<br /> &lt;Name&amp;gt;convert&amp;lt;/Name&amp;gt;<br /> &lt;Licenses&amp;gt;<br /> &lt;License name=&quot;GPL&amp;quot; file=&quot;license.txt&amp;quot; /&amp;gt;<br /> &lt;/Licenses&amp;gt;<br /> &lt;ForcedInstallation&amp;gt;true&amp;lt;/ForcedInstallation&amp;gt;<br /> [removed]installshortcut.qs[removed]<br />&lt;/Package&amp;gt;<br /><code>


==Building a Windows Installer==
The installshortcut.qs:
 
First head over to http://download.qt.io/official_releases/qt-installer-framework/1.5.0/ and download the package for your operating system.


After installation — we assume '''c:\qinstfw''' — we need to create some files holding the installer meta data. I suggest creating a directory in your source root directory called “installer” with this structure:
</code><br />function Component() {<br />}
 
The installer can be instructed to install one or more '''packages'''. They are all located in the packages subdirectory. In the above example we have one package called '''my-package'''. In the meta directory we store the license, an installation script for the Windows Shortcut and a package.xml containing the meta data:


package.xml contains:
Component.prototype.createOperations = function() {<br /> component.createOperations();


The installshortcut.qs:
if ( installer.value(&quot;os&amp;quot;) === &quot;win&amp;quot; ) {<br /> component.addOperation(<br /> &quot;CreateShortcut&amp;quot;,<br /> &quot;<code>TargetDir<code>/my-executable.exe&amp;quot;,<br /> &quot;</code>StartMenuDir</code>/My Executable.lnk&amp;quot;<br /> );<br /> }<br />}<br /><code>


And finally the main configuration file contained in config:
And finally the main configuration file contained in config:


config.xml
config.xml
</code><br />&amp;lt;?xml version=&quot;1.0&amp;quot; encoding=&quot;UTF-8&amp;quot;?&amp;gt;<br />&lt;Installer&amp;gt;<br /> &lt;Name&amp;gt;My Executable&amp;lt;/Name&amp;gt;<br /> &lt;Version&amp;gt;1.0&amp;lt;/Version&amp;gt;<br /> &amp;lt;Title&amp;amp;gt;Description&amp;amp;lt;/Title&amp;amp;gt;<br /> &lt;Publisher&amp;gt;Simon Wilper&amp;lt;/Publisher&amp;gt;<br /> &lt;StartMenuDir&amp;gt;My Application&amp;lt;/StartMenuDir&amp;gt;<br /> &lt;TargetDir&amp;gt;<code>rootDir<code>my-application&amp;lt;/TargetDir&amp;gt;<br /> &lt;UninstallerName&amp;gt;Uninstall&amp;lt;/UninstallerName&amp;gt;<br />&lt;/Installer&amp;gt;<br /></code>


Now to create the installer run the binarycreator:
Now to create the installer run the binarycreator:


We call the binarycreator from the installer root directory, so we have relative locations to the config.xml and packages subdirectory.
<code><br />c:.exe —offline-only -c config\config.xml -p packages setup.exe<br /></code>

Revision as of 09:46, 24 February 2015

h1. Deploying Windows Applications

[toc depth="2&quot;]

What does that mean?

In most cases the Qt applications you create don't reside on your development machine just to please you. You want to distribute them and make them run without any further hazzle and dependency installations on any Windows machine: Copy, Double-Click and Run.

Normally Qt applications are compiled and linked against shared libraries (Windows: DLL=Dynamic Link Library, Unix: .so=Shared Object). When the compiled program is executed the code from the libraries needed is loaded at runtime. The point is now to know which libraries have to be shipped along with your application to make it run without having a full Qt installation on the target system.

List of Libraries needed

Besides your compiled .exe file you need some libraries contained in the same directory as the executable.
All needed libraries are located in your Qt installation bin directory, e.g. C:.4\mingw491_32\bin. If you have installed more than one development kits you need to copy the libraries from the correct kit of course.

WARNING: Don't take the library files from the QtCreator directory which is compiled with MSVC and has slightly different entry points.

In either case you need the following non-Qt libraries. The list was created from a Qt 5.4 installation:

{background:#009900;color:white}. |. Library Name |. Size |_. Remarks |
|>. icudt53.dll | 21M | Unicode Lib |
|>. icuin53.dll | 3.6M | Unicode Lib |
|>. icuuc53.dll | 2.0M | Unicode Lib |
|>. libgcc_s_dw2-1.dll | 118K | GCC Lib |
|>. libstdc+–6.dll | 1003K | Standard C+ Library |
|>. libwinpthread-1.dll | 48K | Pthreads for Windows |

Some might argue that there might arise a small problem with shipping 27M ICU libraries. If you don't need ICU (http://site.icu-project.org/) you need to recompile Qt with configure -without-icu.

Next we need — depending on what your application needs — to copy the Qt DLLs. First have a look at your .pro file that has a line like:

QT ''= widgets<code>
<br />In this case you need to copy the following files:
<br />{background:#009900;color:white}. |''. Library Name |''. Size |_. Remarks |<br />|&gt;. Qt5Core.dll | 4.7M | Qt Core classes  always needed! |<br />|&gt;. Qt5Gui.dll | 5.0M | Graphical User Interface Classes |<br />|&gt;. Qt5Widgets.dll | 6.2M | Widget Classes |
<br />So far for the core libraries to make the program run on other machines. But wait. Something important is missing:
<br />h2. Platform Plugins
<br />For some reason some vital functions for starting Windows applications are contained in '''qwindows.dll''' Located in '''C:.4\mingw491_32\plugins\platforms'''. Copying this file to the same directory to the other DLLs would not work. This file is expected in the '''platforms''' subdirectory:
<br />


.
├── Qt5Core.dll
├── Qt5Gui.dll
├── Qt5Sql.dll
├── Qt5Widgets.dll
├── icudt53.dll
├── icuin53.dll
├── icuuc53.dll
├── libgcc_s_dw2-1.dll
├── libstdc–6.dll
├── libwinpthread-1.dll
└── platforms
   └── qwindows.dll

<br />Now your application is good to go and able to run on other machines not having a fully blown Qt installation preinstalled. Unfortunately you still need to ship a total of approx. 45M (half without ICU).
<br />h2. Database Applications
<br />When shipping applications that need to establish a database connection you need to ship the '''Qt5Sql.dll''' and the database driver library you use to connect to the database. In this example we make use of SQLite:
<br />


.
├── Qt5Core.dll
├── Qt5Gui.dll
├── Qt5Widgets.dll
├── Qt5Sql.dll
├── icudt53.dll
├── icuin53.dll
├── icuuc53.dll
├── libgcc_s_dw2-1.dll
├── libstdc+–6.dll
├── libwinpthread-1.dll
├── platforms
│   └── qwindows.dll
└── sqldrivers
└── qsqlite.dll

You noticed that we created a sqldrivers directory holding the sqlite.dll copied from '''C:.4\mingw491_32\plugins\sqldrivers'''

== Building a Windows Installer ==

First head over to http://download.qt.io/official_releases/qt-installer-framework/1.5.0/ and download the package for your operating system.

After installation  we assume *c:  we need to create some files holding the installer meta data. I suggest creating a directory in your source root directory called &quot;installer&amp;quot; with this structure:


.
├── config
│   └── config.xml
└── packages
└── my-package
├── data
│ ├── my-executable.exe
│ ├── …
│ .
└── meta
├── installshortcut.qs
├── license.txt
└── package.xml

The installer can be instructed to install one or more '''packages'''. They are all located in the packages subdirectory. In the above example we have one package called '''my-package'''. In the meta directory we store the license, an installation script for the Windows Shortcut and a package.xml containing the meta data:

package.xml contains:


&lt;?xml version="1.0&quot; encoding="UTF-8&quot;?&gt;
<Package&gt;
<DisplayName&gt;Name of this Package&lt;/DisplayName&gt;
<Description&gt;Short description&lt;/Description&gt;
<Version&gt;1.0&lt;/Version&gt;
<ReleaseDate&gt;2015-01-10&lt;/ReleaseDate&gt;
<Name&gt;convert&lt;/Name&gt;
<Licenses&gt;
<License name="GPL&quot; file="license.txt&quot; /&gt;
</Licenses&gt;
<ForcedInstallation&gt;true&lt;/ForcedInstallation&gt;
[removed]installshortcut.qs[removed]
</Package&gt;

The installshortcut.qs:


function Component() {
}

Component.prototype.createOperations = function() {
component.createOperations();

if ( installer.value("os&quot;) === "win&quot; ) {
component.addOperation(
"CreateShortcut&quot;,
"

TargetDir<code>/my-executable.exe&amp;quot;,<br /> &quot;

StartMenuDir/My Executable.lnk&quot;
);
}
}

And finally the main configuration file contained in config:

config.xml


&lt;?xml version="1.0&quot; encoding="UTF-8&quot;?&gt;
<Installer&gt;
<Name&gt;My Executable&lt;/Name&gt;
<Version&gt;1.0&lt;/Version&gt;
&lt;Title&amp;gt;Description&amp;lt;/Title&amp;gt;
<Publisher&gt;Simon Wilper&lt;/Publisher&gt;
<StartMenuDir&gt;My Application&lt;/StartMenuDir&gt;
<TargetDir&gt;

rootDir<code>my-application&amp;lt;/TargetDir&amp;gt;<br /> &lt;UninstallerName&amp;gt;Uninstall&amp;lt;/UninstallerName&amp;gt;<br />&lt;/Installer&amp;gt;<br />

Now to create the installer run the binarycreator:

<br />c:.exe offline-only -c config\config.xml -p packages setup.exe<br />