1# Qt {#sec-language-qt}
2
3Writing Nix expressions for Qt libraries and applications is largely similar to that for other C++ software.
4This section assumes some knowledge of the latter.
5
6The major caveat with Qt applications is that Qt uses a plugin system to load additional modules at runtime.
7In Nixpkgs, we wrap Qt applications to inject environment variables telling Qt where to discover the required plugins and QML modules.
8
9This effectively makes the runtime dependencies pure and explicit at build-time, at the cost of introducing
10an extra indirection.
11
12## Nix expression for a Qt package (default.nix) {#qt-default-nix}
13
14```nix
15{ stdenv, qt6 }:
16
17stdenv.mkDerivation {
18 pname = "myapp";
19 version = "1.0";
20
21 buildInputs = [ qt6.qtbase ];
22 nativeBuildInputs = [ qt6.wrapQtAppsHook ];
23}
24```
25
26The same goes for Qt 5 where libraries and tools are under `libsForQt5`.
27
28Any Qt package should include `wrapQtAppsHook` or `wrapQtAppsNoGuiHook` in `nativeBuildInputs`, or explicitly set `dontWrapQtApps` to bypass generating the wrappers.
29
30::: {.note}
31
32`wrapQtAppsHook` propagates plugins and QML components from `qtwayland` on platforms that support it, to allow applications to act as native Wayland clients. It should be used for all graphical applications.
33
34`wrapQtAppsNoGuiHook` does not propagate `qtwayland` to reduce closure size for purely command-line applications.
35
36:::
37
38## Packages supporting multiple Qt versions {#qt-versions}
39
40If your package is a library that can be built with multiple Qt versions, you may want to take Qt modules as separate arguments (`qtbase`, `qtdeclarative` etc.), and invoke the package from `pkgs/top-level/qt5-packages.nix` or `pkgs/top-level/qt6-packages.nix` using the respective `callPackage` functions.
41
42Applications should generally be built with upstream's preferred Qt version.
43
44## Locating additional runtime dependencies {#qt-runtime-dependencies}
45
46Add entries to `qtWrapperArgs` to modify the wrappers created by
47`wrapQtAppsHook`:
48
49```nix
50{ stdenv, qt6 }:
51
52stdenv.mkDerivation {
53 # ...
54 nativeBuildInputs = [ qt6.wrapQtAppsHook ];
55 qtWrapperArgs = [ "--prefix PATH : /path/to/bin" ];
56}
57```
58
59The entries are passed as arguments to [wrapProgram](#fun-wrapProgram).
60
61If you need more control over the wrapping process, set `dontWrapQtApps` to disable automatic wrapper generation,
62and then create wrappers manually in `fixupPhase`, using `wrapQtApp`, which itself is a small wrapper over [wrapProgram](#fun-wrapProgram):
63
64The `makeWrapper` arguments required for Qt are also exposed in the environment as `$qtWrapperArgs`.
65
66```nix
67{
68 stdenv,
69 lib,
70 wrapQtAppsHook,
71}:
72
73stdenv.mkDerivation {
74 # ...
75 nativeBuildInputs = [ wrapQtAppsHook ];
76 dontWrapQtApps = true;
77 preFixup = ''
78 wrapQtApp "$out/bin/myapp" --prefix PATH : /path/to/bin
79 '';
80}
81```
82
83::: {.note}
84`wrapQtAppsHook` ignores files that are non-ELF executables.
85This means that scripts won't be automatically wrapped so you'll need to manually wrap them as previously mentioned.
86An example of when you'd always need to do this is with Python applications that use PyQt.
87:::