From 76081bed3a06aaa25dcf0fe355c9a79f2f7a593d Mon Sep 17 00:00:00 2001 From: K900 Date: Thu, 8 Feb 2024 09:54:09 +0300 Subject: [PATCH] doc/qt: refresh Make examples don't require a custom callPackage, remove note on multiversioning, reword a few things. Fixes #287015 --- doc/languages-frameworks/qt.section.md | 57 +++++++++++--------------- 1 file changed, 23 insertions(+), 34 deletions(-) diff --git a/doc/languages-frameworks/qt.section.md b/doc/languages-frameworks/qt.section.md index 5d2850de3dca..1edceb53cfe4 100644 --- a/doc/languages-frameworks/qt.section.md +++ b/doc/languages-frameworks/qt.section.md @@ -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 }: