Open-source project
QuasarApp/CQtDeployer avatar
QuasarApp/CQtDeployer

CQtDeployer: shipping a Qt app without hand-assembling its libraries

This project is used to deploy applications written using QML, qt or other С / С++ frameworks.

653 stars93 forksC++LGPL-3.0

At a glance

What is it?
CQtDeployer is a console tool that works out which libraries a Qt, QML or plain C/C++ executable depends on, copies them into a deployable tree with a launch script, and can wrap that tree in a deb, snap, DMG, zip or installer. The part that sets it apart is cross-deployment, deploying a Windows target from a Linux host and the reverse.
Who is it for?
Adopt CQtDeployer if you ship a Qt or QML application and currently assemble its runtime libraries by hand or with a platform-specific script, and if you need to produce a Windows build from a Linux CI machine. Do not adopt it if your application is statically linked already, since the whole tool exists to solve dynamic dependency resolution.
Can I use it commercially?
Yes, with conditions. LGPL-3.0 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly C++, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The job is dependency discovery plus a launch script

CQtDeployer helps you to extract all libraries your executable depends on and to create a launch script for your application. That is the whole job, and it is a job that looks trivial until you have done it.

A Qt application on Linux links against a set of shared objects that live in versioned directories under a Qt installation, and the exact set depends on the Qt version, the compiler, the architecture and which modules you used. Assembling that set by hand, then writing a wrapper script that sets the library path correctly, then redoing it for every new build, is exactly the kind of work a tool should own.

The README lists the key differences of the program. Performance, where it claims the application deploys several times faster, up to 10 seconds. Flexibility, through flags that help you configure the deployment for your needs. Cross-deployment, supporting Windows, Linux and macOS distributions, which means you can deploy a project for a Windows target on a Linux host and vice versa. And fast installers creation, so that once the deployment is complete you receive a standalone installer for your distribution.

The cross-deployment capability is the one that changes how a team works. A Linux CI machine that produces a Windows installer removes a second build machine from the pipeline, and the README's examples show the qmake path being pointed at a Windows qmake on one line and a macOS qmake on another.

The project also thanks LIEF for the LIEF library that is used to parse the PE, ELF and Mach-O binaries. That is the mechanism under the whole thing, and it is why the same tool handles all three executable formats.

The output formats are chosen per platform, not per target

The supported platform list is short and it maps onto packaging formats rather than onto operating systems in the abstract.

For Linux there are four options: deb, snap, raw binaries and installer. For Windows there are two: raw binaries and installer. For macOS there are three: DMG as an app bundle, zip, and raw binaries.

The asymmetry is deliberate. A deb or a snap is a Linux-specific packaging concept, and a DMG is a macOS one, so raw binaries exist as the common denominator for every platform. That is a useful design for a tool whose job is to produce something shippable rather than something runnable on the developer's machine.

There is one documented gap and it is worth knowing before you plan a release. The README notes that the Qt Installer Framework installer is not available on macOS, because the QIFW tools are not published for that platform, so the `qif` option is skipped gracefully on macOS hosts, with a pointer to the macOS documentation in `md/en/macOS.md` for the details. Graceful degradation is the right behavior, but it means a script that passes `qif` will quietly produce something different on a macOS build agent.

The processor architecture list is x86, x86-64, ARM and ARM64, so both desktop and embedded targets are in scope, which matches the project's origin as a tool for QML applications, many of which run on embedded Linux.

Running it is a single command with a binary and a qmake

The usage section gives the general form and then a worked example, which is the fastest way to understand the interface.

The general form is `cqtdeployer <-bin [params]> [options]`, and the README points to a full list of all options in `md/en/Options.md`. The worked example names a binary, a QML directory and a qmake path, with a trailing `clear` action, running `cqtdeployer -bin myApp -qmlDir ~/MyAppProject/qml -qmake ~/Qt/6.3.1/gcc_64/bin/qmake clear`.

The three arguments map onto the three things the tool has to discover. The `-bin` is the executable. The `-qmlDir` is where the QML resources live, which matters because a QML application carries its QML files and resources separately from the binary, and those have to travel with it. The `-qmake` tells the tool which Qt installation to resolve against, which is the key to finding the right plugin directories and the right library versions.

The `clear` argument is worth noting because it reads as a subcommand rather than an option. There are also trailing action keywords in the other examples, `qif` for installer creation and `qifStyle` for the installer styling, so the tool mixes verbs and flags in one command line.

The README's own examples for the three platforms differ only in the binary name and the qmake path, which is a good sign for the cross-platform claim:

bash
 #linux
 cqtdeployer -bin Guitar  
 
 #windows
 cqtdeployer -bin Guitar.exe -qmake /path/to/qmake.exe

 #macos
 cqtdeployer -bin Guitar -qmake /path/to/Qt/6.10.3/macos/bin/qmake

Note that the Windows example passes the executable with the `.exe` suffix and the macOS example points at a Qt 6.10.3 macOS qmake, while the earlier worked example uses a 6.3.1 Linux toolchain.

Installer creation is a second pass over the deployed tree

Building the installer is not a separate tool. Once a deployment exists, the same command produces the installer, and the README shows the `qif` action doing that.

bash
 #linux
 cqtdeployer -bin Application qif
 
 #windows
 cqtdeployer -bin Application.exe -qmake /path/to/qmake.exe qif

The styling is a further option, and there are two forms of it. A named style, shown here as `quasar`:

bash
 #linux
 cqtdeployer -bin Application qif -qifStyle quasar
 
 #windows
 cqtdeployer -bin Application.exe -qmake /path/to/qmake.exe qif -qifStyle quasar

And a path to a CSS file, which is the form you would use for a custom branded installer:

bash
 #linux
 cqtdeployer -bin Application qif -qifStyle path/to/myStyle.css
 
 #windows
 cqtdeployer -bin Application.exe -qmake /path/to/qmake.exe qif -qifStyle path/to/myStyle.css

The `qif` action stands for the Qt Installer Framework, and `qifStyle` takes either a bundled style name or a stylesheet path. The README's screenshots show the resulting project installer for each of these variants, which is a reasonable way to understand the output before running it yourself.

The whole sequence is worth internalizing as a pipeline. Deployment produces the runtime tree, and the installer step wraps that tree. The README's supported-platforms list is what tells you the tree can then be turned into a deb or a snap or a DMG, so the packaging step and the installer step are two different ways of shipping the same deployed output.

It installs from a Snap, from source, or from a GitHub Action

The build and install section is short and defers the details. It points to a wiki page at `md/en/Build-and-Install.md` for building and installation instructions, and the repository layout supports that with a `CMakeLists.txt`, a `src/` directory, a `tests/` directory and a `submodules/` directory alongside a `.gitmodules` file, so the source build has vendored dependencies.

The distribution channel that is documented in the README itself is the Snap, with a badge pointing at the snapcraft listing. The README also points at a GitHub Action, with a workflow snippet:

yaml
- name: Install CQtDeployer
  uses: QuasarApp/[email protected]

That is a setup action rather than a deployment action, and it is the piece that belongs in a CI pipeline. The README names it as available in GitHub Actions and links to the marketplace entry.

The Snap route and the Action route solve the same problem, which is getting a specific version of CQtDeployer onto a build machine without a manual install. The Snap is the desktop distribution and the Action is the CI distribution, and they are versioned independently, so a pipeline can pin one while a developer has the other.

The project also publishes a documentation site, with a link in the README to a hosted documentation build, plus a `mkdocs.yml` and a `md/` directory in the repository, which is where the option reference and the per-platform notes live. The `doxygen.conf.in` file suggests the API documentation is generated from the source with Doxygen.

Compared with a platform script and with the Qt Installer Framework alone

The alternative approaches differ in how much of the problem they solve.

A hand-written deployment script, which is what most Qt projects end up with, solves the problem for one platform and one Qt version. It is a shell or CMake script that copies libraries, copies Qt plugins, and writes a wrapper that sets LD_LIBRARY_PATH or PATH. It works, and it is the thing you already have if you are reading this. The cost is that it has to be maintained by somebody, it breaks when the Qt version changes, and it does not cross platforms at all.

CQtDeployer takes over exactly that work, using the LIEF library to read PE, ELF and Mach-O binaries and work out the real dependency set rather than a guessed one. The practical difference is that a wrong guess in a hand-written script shows up as a failed launch on a user's machine, while a wrong guess here is a deployment that a script can be pointed at and reproduced.

The other alternative is building an installer with the Qt Installer Framework directly. That is what the `qif` action wraps, and it is a different layer: QIF produces a self-extracting installer with a maintenance and update mode, but it does not gather your application's Qt runtime libraries for you. CQtDeployer is the step before it.

The trade-offs are about scope and platform coverage. CQtDeployer supports deb, snap and DMG outputs, which QIF alone does not produce, and it can target a foreign platform from the host. What you give up is control over the fine details of the package, since the deb and snap it generates are its own rather than yours, and a project with a hand-tuned packaging setup will keep that setup and use CQtDeployer only for the runtime tree.

The licence is LGPL-3.0, with the terms in the LICENSE file, which is a permissive-enough licence for a build tool and carries the usual obligations for a modified library distribution, and this is not legal advice. The repository is not archived, the last push was on 2026-10-20, and the release tags carry four-part version numbers such as v1.6.2533.f170632, with the suffix appearing to track a build identifier.

Editorial conclusion

Adopt CQtDeployer if you ship a Qt or QML application and currently assemble its runtime libraries by hand or with a platform-specific script, and if you need to produce a Windows build from a Linux CI machine. Do not adopt it if your application is statically linked already, since the whole tool exists to solve dynamic dependency resolution. Verify first that the Qt version you deploy with is the one the tool expects, that your target architecture is among the supported list, and that the packaging format you want is offered on your host platform, since the README notes the Qt Installer Framework path is skipped on macOS hosts.

Frequently asked questions

What does CQtDeployer do?

It helps you to extract all libraries your executable depends on and to create a launch script for your application. It uses the LIEF library to parse PE, ELF and Mach-O binaries, so the dependency set is discovered rather than assumed.

Which packaging formats does CQtDeployer support?

On Linux it produces deb, snap, raw binaries and an installer. On Windows it produces raw binaries and an installer. On macOS it produces a DMG app bundle, a zip and raw binaries. The processor architectures listed are x86, x86-64, ARM and ARM64.

Can CQtDeployer build a Windows app from a Linux machine?

Yes. The README describes cross-deployment as a key difference, supporting Windows, Linux and macOS distributions, which means you can deploy a project for a Windows target on a Linux host and vice versa. The examples show the qmake path being pointed at a Windows qmake.

How do I create an installer with CQtDeployer?

Pass the `qif` action to build with the Qt Installer Framework, and use `qifStyle` to pick a bundled style such as `quasar` or point at a CSS file such as `path/to/myStyle.css`. The README notes that `qif` is skipped gracefully on macOS hosts because the QIFW tools are not published for that platform.

How do I install CQtDeployer in a CI pipeline?

The README points to the setup-cqtdeployer GitHub Action, used as `uses: QuasarApp/[email protected]`, and the project is also distributed as a Snap through the Snap Store. Build and installation instructions from source are in the wiki page at md/en/Build-and-Install.md.

Official sources

  1. License: LGPL-3.0
  2. Project website
  3. QuasarApp/CQtDeployer on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/quasarapp-cqtdeployer.svg)](https://hysenlabs.com/projects/quasarapp-cqtdeployer)

Was this useful?