Cross-Platform Deployment

Packaging Qt applications for Linux, Windows, and embedded targets — static linking and deploy tools.

3 min read
18078 chars

Deployment Overview

Qt apps require Qt libraries at runtime unless statically linked. Deployment means bundling everything the user needs to run your app on a clean machine.

PlatformToolOutput
WindowswindeployqtFolder with DLLs
Linux desktoplinuxdeployqt or AppImageAppImage bundle
macOSmacdeployqt.app bundle
Embedded LinuxCross-compiled binary + sysroot libsBinary + libs

Build for Release

Always build in Release mode for deployment:

cmake -B build-release \
    -DCMAKE_BUILD_TYPE=Release \
    -DCMAKE_PREFIX_PATH=/path/to/Qt/6.x/gcc_64

cmake --build build-release --parallel $(nproc)

# Strip debug symbols to reduce size
strip build-release/MyApp

Windows Deployment — windeployqt

windeployqt copies all required Qt DLLs and plugins next to your .exe:

# Build first
cmake --build build-release --config Release

# Run windeployqt
cd build-release
windeployqt --release --qmldir ../qml MyApp.exe

The output folder will contain:

MyApp.exe
Qt6Core.dll
Qt6Widgets.dll
Qt6Network.dll
platforms/qwindows.dll
imageformats/qjpeg.dll
...

Zip this folder and distribute — no Qt installation needed on the target PC.

Optional — Create an Installer with NSIS or Inno Setup

# Using Inno Setup (free)
# Create a .iss script pointing to your deployment folder
# Compile → produces MyApp-Setup.exe

Linux Desktop — AppImage

AppImage bundles everything into a single executable file:

# Install linuxdeployqt
wget -q "https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage"
chmod +x linuxdeployqt-continuous-x86_64.AppImage

# Create AppDir structure
mkdir -p AppDir/usr/bin
cp build-release/MyApp AppDir/usr/bin/

# Create .desktop file
cat > AppDir/MyApp.desktop << EOF
[Desktop Entry]
Name=MyApp
Exec=MyApp
Icon=myapp
Type=Application
Categories=Utility;
EOF

cp resources/icons/myapp.png AppDir/

# Package
./linuxdeployqt-continuous-x86_64.AppImage \
    AppDir/MyApp.desktop \
    -qmake=/path/to/Qt/6.x/gcc_64/bin/qmake \
    -appimage

Output: MyApp-x86_64.AppImage — a single portable executable.


Static Linking

Static linking embeds all Qt libraries into the binary — no DLLs needed, but binary size grows significantly.

Build Qt Statically

# Configure Qt for static build
./configure -static -release -prefix ~/Qt-static \
    -opensource -confirm-license \
    -no-feature-sql -no-feature-printer

cmake --build . --parallel $(nproc)
cmake --install .
cmake -B build-static \
    -DCMAKE_BUILD_TYPE=Release \
    -DCMAKE_PREFIX_PATH=~/Qt-static

The resulting binary is self-contained:

ldd build-static/MyApp
# Should show only system libs (libc, libstdc++, etc.)

Embedded Linux Deployment

For embedded targets, deploy the binary plus required shared libraries:

# Find shared library dependencies
arm-linux-gnueabihf-objdump -p MyHMI | grep NEEDED
# or
readelf -d MyHMI | grep NEEDED

# Copy Qt libs to target rootfs
scp ~/Qt-arm/lib/libQt6Core.so.6     pi@raspberrypi.local:/usr/lib/
scp ~/Qt-arm/lib/libQt6Widgets.so.6  pi@raspberrypi.local:/usr/lib/
scp ~/Qt-arm/lib/libQt6Quick.so.6    pi@raspberrypi.local:/usr/lib/

# Copy Qt platform plugins
scp -r ~/Qt-arm/plugins/platforms/   pi@raspberrypi.local:/usr/lib/qt6/plugins/

# Copy binary
scp build-rpi/MyHMI pi@raspberrypi.local:~/

# Run
ssh pi@raspberrypi.local \
    "QT_QPA_PLATFORM=eglfs LD_LIBRARY_PATH=/usr/lib ./MyHMI"

CMake Install Rules

Define install targets so cmake --install copies the right files:

install(TARGETS MyApp
    RUNTIME DESTINATION bin       # executable
    LIBRARY DESTINATION lib       # shared libs
    ARCHIVE DESTINATION lib       # static libs
)

# Install QML files
install(DIRECTORY qml/
    DESTINATION share/MyApp/qml
)

# Install Qt plugins (platform, imageformat, etc.)
install(DIRECTORY ${Qt6_DIR}/../../../plugins/platforms/
    DESTINATION plugins/platforms
)
cmake --install build-release --prefix /opt/myapp

Version Information

Embed version info at build time:

configure_file(
    src/version.h.in
    ${CMAKE_BINARY_DIR}/version.h
)
target_include_directories(MyApp PRIVATE ${CMAKE_BINARY_DIR})
// src/version.h.in
#pragma once
#define APP_VERSION "@PROJECT_VERSION@"
#define APP_NAME    "@PROJECT_NAME@"
#define BUILD_DATE  "@BUILD_DATE@"
// Usage
#include "version.h"
qDebug() << "Version:" << APP_VERSION;

Summary

PlatformToolNotes
WindowswindeployqtCopies DLLs next to .exe
Linux desktoplinuxdeployqt / AppImageSingle portable file
macOSmacdeployqt.app bundle
Embedded LinuxManual sysroot copyMatch Qt version to target rootfs
All platformsStatic buildOne binary, no deps, larger size

You now have the full Qt C++ track — from environment setup to production deployment on both desktop and embedded Linux targets.