doc/qt: refresh

Make examples don't require a custom callPackage, remove note on multiversioning, reword a few things.

Fixes #287015
This commit is contained in:
K900 2024-02-08 09:54:09 +03:00
parent 0302e47841
commit 76081bed3a

View File

@ -3,72 +3,61 @@
Writing Nix expressions for Qt libraries and applications is largely similar as for other C++ software.
This section assumes some knowledge of the latter.
The major caveat with Qt applications is that Qt uses a plugin system to load additional modules at runtime,
from a list of well-known locations. In Nixpkgs, we patch QtCore to instead use an environment variable,
and wrap Qt applications to set it to the right paths. This effectively makes the runtime dependencies
pure and explicit at build-time, at the cost of introducing an extra indirection.
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.
## Nix expression for a Qt package (default.nix) {#qt-default-nix}
```nix
{ stdenv, lib, qtbase, wrapQtAppsHook }:
{ stdenv, lib, qt6, wrapQtAppsHook }:
stdenv.mkDerivation {
pname = "myapp";
version = "1.0";
buildInputs = [ qtbase ];
nativeBuildInputs = [ wrapQtAppsHook ];
buildInputs = [ qt6.qtbase ];
nativeBuildInputs = [ qt6.wrapQtAppsHook ];
}
```
It is important to import Qt modules directly, that is: `qtbase`, `qtdeclarative`, etc. *Do not* import Qt package sets such as `qt5` because the Qt versions of dependencies may not be coherent, causing build and runtime failures.
Any Qt package should include `wrapQtAppsHook` in `nativeBuildInputs`, or explicitly set `dontWrapQtApps` to bypass generating the wrappers.
Additionally all Qt packages must include `wrapQtAppsHook` in `nativeBuildInputs`, or you must explicitly set `dontWrapQtApps`.
::: {.note}
Graphical Linux applications should also include `qtwayland` in `buildInputs`, to ensure the Wayland platform plugin is available.
`pkgs.callPackage` does not provide injections for `qtbase` or the like.
Instead you want to either use `pkgs.libsForQt5.callPackage`, or `pkgs.qt6Packages.callPackage`, depending on the Qt version you want to use.
This may become default in the future, see [NixOS/nixpkgs#269674](https://github.com/NixOS/nixpkgs/pull/269674).
:::
For example (from [here](https://github.com/NixOS/nixpkgs/blob/2f9286912cb215969ece465147badf6d07aa43fe/pkgs/top-level/all-packages.nix#L30106))
## Packages supporting multiple Qt versions {#qt-versions}
```nix
zeal-qt5 = libsForQt5.callPackage ../data/documentation/zeal { };
zeal-qt6 = qt6Packages.callPackage ../data/documentation/zeal { };
zeal = zeal-qt5;
```
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.
## Locating runtime dependencies {#qt-runtime-dependencies}
Applications should generally be built with upstream's preferred Qt version.
Qt applications must be wrapped to find runtime dependencies.
Include `wrapQtAppsHook` in `nativeBuildInputs`:
```nix
{ stdenv, wrapQtAppsHook }:
stdenv.mkDerivation {
# ...
nativeBuildInputs = [ wrapQtAppsHook ];
}
```
## Locating additional runtime dependencies {#qt-runtime-dependencies}
Add entries to `qtWrapperArgs` are to modify the wrappers created by
`wrapQtAppsHook`:
```nix
{ stdenv, wrapQtAppsHook }:
{ stdenv, qt6 }:
stdenv.mkDerivation {
# ...
nativeBuildInputs = [ wrapQtAppsHook ];
nativeBuildInputs = [ qt6.wrapQtAppsHook ];
qtWrapperArgs = [ ''--prefix PATH : /path/to/bin'' ];
}
```
The entries are passed as arguments to [wrapProgram](#fun-wrapProgram).
Set `dontWrapQtApps` to stop applications from being wrapped automatically.
Wrap programs manually with `wrapQtApp`, using the syntax of
[wrapProgram](#fun-wrapProgram):
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`.
```nix
{ stdenv, lib, wrapQtAppsHook }: