2020-11-30 05:30:29 +01:00
# Qt {#sec-language-qt}
2021-01-10 18:34:34 +01:00
Writing Nix expressions for Qt libraries and applications is largely similar as for other C++ software.
This section assumes some knowledge of the latter.
2020-11-30 05:30:29 +01:00
2024-02-08 07:54:09 +01:00
The major caveat with Qt applications is that Qt uses a plugin system to load additional modules at runtime.
In Nixpkgs, we wrap Qt applications to inject environment variables telling Qt where to discover the required plugins and QML modules.
This effectively makes the runtime dependencies pure and explicit at build-time, at the cost of introducing
an extra indirection.
2020-11-30 05:30:29 +01:00
## Nix expression for a Qt package (default.nix) {#qt-default-nix}
2023-06-10 18:13:33 +02:00
```nix
2024-03-04 04:16:54 +01:00
{ stdenv, qt6 }:
2020-11-30 05:30:29 +01:00
2021-01-10 18:34:34 +01:00
stdenv.mkDerivation {
2020-11-30 05:30:29 +01:00
pname = "myapp";
version = "1.0";
2024-02-08 07:54:09 +01:00
buildInputs = [ qt6.qtbase ];
nativeBuildInputs = [ qt6.wrapQtAppsHook ];
2020-11-30 05:30:29 +01:00
}
```
2024-03-04 04:16:54 +01:00
The same goes for Qt 5 where libraries and tools are under `libsForQt5` .
2024-02-08 07:54:09 +01:00
Any Qt package should include `wrapQtAppsHook` in `nativeBuildInputs` , or explicitly set `dontWrapQtApps` to bypass generating the wrappers.
2023-09-18 03:35:23 +02:00
2024-02-08 07:54:09 +01:00
::: {.note}
2024-03-04 04:16:54 +01:00
Qt 6 graphical applications should also include `qtwayland` in `buildInputs` on Linux (but not on platforms e.g. Darwin, where `qtwayland` is not available), to ensure the Wayland platform plugin is available.
2023-09-18 03:35:23 +02:00
2024-02-08 07:54:09 +01:00
This may become default in the future, see [NixOS/nixpkgs#269674 ](https://github.com/NixOS/nixpkgs/pull/269674 ).
:::
2023-09-18 03:35:23 +02:00
2024-02-08 07:54:09 +01:00
## Packages supporting multiple Qt versions {#qt-versions}
2021-01-10 18:34:34 +01:00
2024-02-08 07:54:09 +01:00
If 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.
2020-11-30 05:30:29 +01:00
2024-02-08 07:54:09 +01:00
Applications should generally be built with upstream's preferred Qt version.
2021-01-10 18:34:34 +01:00
2024-02-08 07:54:09 +01:00
## Locating additional runtime dependencies {#qt-runtime-dependencies}
2021-01-10 18:34:34 +01:00
2021-01-12 12:50:23 +01:00
Add entries to `qtWrapperArgs` are to modify the wrappers created by
`wrapQtAppsHook` :
2020-11-30 05:30:29 +01:00
```nix
2024-02-08 07:54:09 +01:00
{ stdenv, qt6 }:
2020-11-30 05:30:29 +01:00
2021-01-10 18:34:34 +01:00
stdenv.mkDerivation {
# ...
2024-02-08 07:54:09 +01:00
nativeBuildInputs = [ qt6.wrapQtAppsHook ];
2020-11-30 05:30:29 +01:00
qtWrapperArgs = [ ''--prefix PATH : /path/to/bin'' ];
}
```
2021-01-10 18:34:34 +01:00
The entries are passed as arguments to [wrapProgram ](#fun-wrapProgram ).
2024-02-08 07:54:09 +01:00
If you need more control over the wrapping process, set `dontWrapQtApps` to disable automatic wrapper generation,
and then create wrappers manually in `fixupPhase` , using `wrapQtApp` , which itself is a small wrapper over [wrapProgram ](#fun-wrapProgram ):
The `makeWrapper` arguments required for Qt are also exposed in the environment as `$qtWrapperArgs` .
2020-11-30 05:30:29 +01:00
```nix
2021-01-10 18:34:34 +01:00
{ stdenv, lib, wrapQtAppsHook }:
2020-11-30 05:30:29 +01:00
2021-01-10 18:34:34 +01:00
stdenv.mkDerivation {
# ...
nativeBuildInputs = [ wrapQtAppsHook ];
2020-11-30 05:30:29 +01:00
dontWrapQtApps = true;
preFixup = ''
wrapQtApp "$out/bin/myapp" --prefix PATH : /path/to/bin
'';
}
```
2021-06-05 21:22:45 +02:00
::: {.note}
2021-01-11 19:09:48 +01:00
`wrapQtAppsHook` ignores files that are non-ELF executables.
This means that scripts won't be automatically wrapped so you'll need to manually wrap them as previously mentioned.
An example of when you'd always need to do this is with Python applications that use PyQt.
:::