···1+--- a/config.py 2025-08-03 00:37:13.058374602 +0200
2++++ b/config.py 2025-08-03 00:45:51.869382363 +0200
3+@@ -24,10 +24,18 @@
4+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
5+ # SOFTWARE.
6+7+-from libqtile import bar, layout, qtile, widget
8++from libqtile import bar, layout, qtile, widget, hook
9+ from libqtile.config import Click, Drag, Group, Key, Match, Screen
10+ from libqtile.lazy import lazy
11+ from libqtile.utils import guess_terminal
12++from libqtile.log_utils import logger
13++
14++
15++@hook.subscribe.startup
16++def print_ready():
17++ logger.warning("ready!") # warning to make it always visible
18++
19++
20+21+ mod = "mod4"
22+ terminal = guess_terminal()
···1+{ lib, ... }:
2+{
3+ name = "qtile-extras";
4+5+ meta = {
6+ maintainers = with lib.maintainers; [
7+ sigmanificient
8+ gurjaka
9+ ];
10+ };
11+12+ nodes.machine =
13+ {
14+ pkgs,
15+ lib,
16+ ...
17+ }:
18+ let
19+ # We create a custom Qtile configuration file that adds a widget from
20+ # qtile-extras to the bar. This ensure that the qtile-extras package
21+ # also works, and that extraPackages behave as expected.
22+ config-deriv = pkgs.callPackage ./config.nix { };
23+ in
24+ {
25+ imports = [
26+ ../common/x11.nix
27+ ../common/user-account.nix
28+ ];
29+ test-support.displayManager.auto.user = "alice";
30+31+ services.xserver.windowManager.qtile = {
32+ enable = true;
33+ configFile = "${config-deriv}/config.py";
34+ extraPackages = ps: [ ps.qtile-extras ];
35+ };
36+37+ services.displayManager.defaultSession = lib.mkForce "qtile";
38+39+ environment.systemPackages = [ pkgs.kitty ];
40+ };
41+42+ testScript = ''
43+ from pathlib import Path
44+45+ with subtest("ensure x starts"):
46+ machine.wait_for_x()
47+ machine.wait_for_file("/home/alice/.Xauthority")
48+ machine.succeed("xauth merge ~alice/.Xauthority")
49+50+ with subtest("ensure client is available"):
51+ machine.succeed("qtile --version")
52+53+ with subtest("Qtile signals that it is ready"):
54+ qtile_logfile = Path("/home/alice/.local/share/qtile/qtile.log")
55+56+ machine.succeed(f"mkdir -p {qtile_logfile.parent}")
57+ machine.succeed(f"touch {qtile_logfile}")
58+ machine.succeed(f"sh -c 'tail -f {qtile_logfile} | grep --line-buffered \'ready\' -m 1'")
59+60+ with subtest("ensure we can open a new terminal"):
61+ machine.send_key("meta_l-ret")
62+ machine.wait_for_window(r"alice.*?machine")
63+ machine.screenshot("terminal")
64+ '';
65+}
+22
nixos/tests/qtile/add-startup-hook.patch
···0000000000000000000000
···1+--- a/config.py 2025-08-03 00:37:13.058374602 +0200
2++++ b/config.py 2025-08-03 00:45:51.869382363 +0200
3+@@ -24,10 +24,18 @@
4+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
5+ # SOFTWARE.
6+7+-from libqtile import bar, layout, qtile, widget
8++from libqtile import bar, layout, qtile, widget, hook
9+ from libqtile.config import Click, Drag, Group, Key, Match, Screen
10+ from libqtile.lazy import lazy
11+ from libqtile.utils import guess_terminal
12++from libqtile.log_utils import logger
13++
14++
15++@hook.subscribe.startup
16++def print_ready():
17++ logger.warning("ready!") # warning to make it always visible
18++
19++
20+21+ mod = "mod4"
22+ terminal = guess_terminal()
···3 name = "qtile";
45 meta = {
6- maintainers = with lib.maintainers; [ sigmanificient ];
0007 };
89 nodes.machine =
10- { pkgs, lib, ... }:
000011 let
12- # We create a custom Qtile configuration file that adds a widget from
13- # qtile-extras to the bar. This ensure that the qtile-extras package
14- # also works, and that extraPackages behave as expected.
15-16 config-deriv = pkgs.callPackage ./config.nix { };
17 in
18 {
···3031 services.displayManager.defaultSession = lib.mkForce "qtile";
3233- environment.systemPackages = [ pkgs.kitty ];
00034 };
3536 testScript = ''
0037 with subtest("ensure x starts"):
38 machine.wait_for_x()
39 machine.wait_for_file("/home/alice/.Xauthority")
···42 with subtest("ensure client is available"):
43 machine.succeed("qtile --version")
44000000045 with subtest("ensure we can open a new terminal"):
46- machine.sleep(2)
47 machine.send_key("meta_l-ret")
48 machine.wait_for_window(r"alice.*?machine")
49- machine.sleep(2)
50 machine.screenshot("terminal")
51 '';
52}
···3 name = "qtile";
45 meta = {
6+ maintainers = with lib.maintainers; [
7+ sigmanificient
8+ gurjaka
9+ ];
10 };
1112 nodes.machine =
13+ {
14+ pkgs,
15+ lib,
16+ ...
17+ }:
18 let
19+ # We create a custom Qtile configuration file that adds a
20+ # startup hook to qtile. This ensure we can reproducibly check
21+ # when Qtile is truly ready to receive our inputs
022 config-deriv = pkgs.callPackage ./config.nix { };
23 in
24 {
···3637 services.displayManager.defaultSession = lib.mkForce "qtile";
3839+ environment.systemPackages = [
40+ pkgs.kitty
41+ pkgs.xorg.xwininfo
42+ ];
43 };
4445 testScript = ''
46+ from pathlib import Path
47+48 with subtest("ensure x starts"):
49 machine.wait_for_x()
50 machine.wait_for_file("/home/alice/.Xauthority")
···53 with subtest("ensure client is available"):
54 machine.succeed("qtile --version")
5556+ with subtest("Qtile signals that it is ready"):
57+ qtile_logfile = Path("/home/alice/.local/share/qtile/qtile.log")
58+59+ machine.succeed(f"mkdir -p {qtile_logfile.parent}")
60+ machine.succeed(f"touch {qtile_logfile}")
61+ machine.succeed(f"sh -c 'tail -f {qtile_logfile} | grep --line-buffered \'ready\' -m 1'")
62+63 with subtest("ensure we can open a new terminal"):
064 machine.send_key("meta_l-ret")
65 machine.wait_for_window(r"alice.*?machine")
066 machine.screenshot("terminal")
67 '';
68}
···33 });
3435in
36-stdenv.mkDerivation rec {
37-38- version = "3.2.5";
39 pname = "gnu-smalltalk";
04041 src = fetchurl {
42- url = "mirror://gnu/smalltalk/smalltalk-${version}.tar.xz";
43- sha256 = "1k2ssrapfzhngc7bg1zrnd9n2vyxp9c9m70byvsma6wapbvib6l1";
44 };
4546 patches = [
47 # The awk script incorrectly parsed `glib/glib.h` and was trying to find `glib/gwin32.h`,
48 # that isn't included since we're building only for linux.
49 ./0000-fix_mkorder.patch
050 ];
005152 # The dependencies and their justification are explained at
53 # http://smalltalk.gnu.org/download
···7172 hardeningDisable = [ "format" ];
7374- installFlags = lib.optional emacsSupport "lispdir=$(out)/share/emacs/site-lisp";
7576 # For some reason the tests fail if executated with nix-build, but pass if
77 # executed within nix-shell --pure.
78 doCheck = false;
7980- meta = with lib; {
81 description = "Free implementation of the Smalltalk-80 language";
82 longDescription = ''
83 GNU Smalltalk is a free implementation of the Smalltalk-80 language. It
···86 language, well-versed to scripting tasks.
87 '';
88 homepage = "http://smalltalk.gnu.org/";
89- license = with licenses; [
90 gpl2
91 lgpl2
92 ];
93- platforms = platforms.linux;
94- maintainers = with maintainers; [ ];
95 };
96-}
···33 });
3435in
36+stdenv.mkDerivation (finalAttrs: {
0037 pname = "gnu-smalltalk";
38+ version = "3.2.5";
3940 src = fetchurl {
41+ url = "mirror://gnu/smalltalk/smalltalk-${finalAttrs.version}.tar.xz";
42+ hash = "sha256-gZoV97qKG1X19gucmli63W9hU7P5h7cOexZ+d1XWWsw=";
43 };
4445 patches = [
46 # The awk script incorrectly parsed `glib/glib.h` and was trying to find `glib/gwin32.h`,
47 # that isn't included since we're building only for linux.
48 ./0000-fix_mkorder.patch
49+ ./0001-fix-compilation.patch
50 ];
51+52+ enableParallelBuilding = true;
5354 # The dependencies and their justification are explained at
55 # http://smalltalk.gnu.org/download
···7374 hardeningDisable = [ "format" ];
7576+ installFlags = lib.optional emacsSupport "lispdir=${placeholder "$out"}/share/emacs/site-lisp";
7778 # For some reason the tests fail if executated with nix-build, but pass if
79 # executed within nix-shell --pure.
80 doCheck = false;
8182+ meta = {
83 description = "Free implementation of the Smalltalk-80 language";
84 longDescription = ''
85 GNU Smalltalk is a free implementation of the Smalltalk-80 language. It
···88 language, well-versed to scripting tasks.
89 '';
90 homepage = "http://smalltalk.gnu.org/";
91+ license = with lib.licenses; [
92 gpl2
93 lgpl2
94 ];
95+ platforms = lib.platforms.linux;
96+ maintainers = with lib.maintainers; [ ];
97 };
98+})
···91 description = "Package that implements a pre-document language and tools to process it";
92 homepage = "https://fbb-git.gitlab.io/yodl/";
93 mainProgram = "yodl";
94- license = lib.licenses.agpl3Only; # Upstream did not clarify the license used. https://gitlab.com/fbb-git/yodl/-/issues/4
95 maintainers = with lib.maintainers; [ pSub ];
96 platforms = lib.platforms.linux;
97 };
···91 description = "Package that implements a pre-document language and tools to process it";
92 homepage = "https://fbb-git.gitlab.io/yodl/";
93 mainProgram = "yodl";
94+ license = lib.licenses.agpl3Plus;
95 maintainers = with lib.maintainers; [ pSub ];
96 platforms = lib.platforms.linux;
97 };
···96 '';
9798 passthru = prevAttrs.passthru or { } // {
99- useCudatoolkitRunfile = strings.versionOlder cudaMajorMinorVersion "11.3.999";
100 # The CUDNN used with TensorRT.
101 # If null, the default cudnn derivation will be used.
102 # If a version is specified, the cudnn derivation with that version will be used,
···96 '';
9798 passthru = prevAttrs.passthru or { } // {
099 # The CUDNN used with TensorRT.
100 # If null, the default cudnn derivation will be used.
101 # If a version is specified, the cudnn derivation with that version will be used,
···7 # https://developer.download.nvidia.com/compute/cuda/redist/
8 # Maps a cuda version to the specific version of the manifest.
9 cudaVersionMap = {
10- "11.4" = "11.4.4";
11- "11.5" = "11.5.2";
12- "11.6" = "11.6.2";
13- "11.7" = "11.7.1";
14 "11.8" = "11.8.0";
15 "12.0" = "12.0.1";
16 "12.1" = "12.1.1";
···7 # https://developer.download.nvidia.com/compute/cuda/redist/
8 # Maps a cuda version to the specific version of the manifest.
9 cudaVersionMap = {
000010 "11.8" = "11.8.0";
11 "12.0" = "12.0.1";
12 "12.1" = "12.1.1";
···5in
6options.mkOption {
7 description = "Feature manifest is an attribute set which includes a mapping from package name to release";
8- example = trivial.importJSON ../../../../cuda/manifests/feature_11.5.2.json;
9 type = types.attrsOf Release.type;
10}
···5in
6options.mkOption {
7 description = "Feature manifest is an attribute set which includes a mapping from package name to release";
8+ example = trivial.importJSON ../../../../cuda/manifests/feature_11.8.0.json;
9 type = types.attrsOf Release.type;
10}
···5in
6options.mkOption {
7 description = "Redistributable manifest is an attribute set which includes a mapping from package name to release";
8- example = trivial.importJSON ../../../../cuda/manifests/redistrib_11.5.2.json;
9 type = types.submodule {
10 # Allow any attribute name as these will be the package names
11 freeformType = types.attrsOf Release.type;
···5in
6options.mkOption {
7 description = "Redistributable manifest is an attribute set which includes a mapping from package name to release";
8+ example = trivial.importJSON ../../../../cuda/manifests/redistrib_11.8.0.json;
9 type = types.submodule {
10 # Allow any attribute name as these will be the package names
11 freeformType = types.attrsOf Release.type;
···18 cuda_cudart
19 cuda_nvcc
20 cudaAtLeast
21- cudaOlder
22- cudatoolkit
23 flags
24 ;
25 # versions 2.26+ with CUDA 11.x error with
···54 which
55 autoAddDriverRunpath
56 python3
57- ]
58- ++ lib.optionals (cudaOlder "11.4") [ cudatoolkit ]
59- ++ lib.optionals (cudaAtLeast "11.4") [ cuda_nvcc ];
6061- buildInputs =
62- lib.optionals (cudaOlder "11.4") [ cudatoolkit ]
63- ++ lib.optionals (cudaAtLeast "11.4") [
64- cuda_nvcc # crt/host_config.h
65- cuda_cudart
66- ]
67- # NOTE: CUDA versions in Nixpkgs only use a major and minor version. When we do comparisons
68- # against other version, like below, it's important that we use the same format. Otherwise,
69- # we'll get incorrect results.
70- # For example, lib.versionAtLeast "12.0" "12.0.0" == false.
71- ++ lib.optionals (cudaAtLeast "12.0") [ cuda_cccl ];
7273 env.NIX_CFLAGS_COMPILE = toString [ "-Wno-unused-function" ];
74···80 makeFlags = [
81 "PREFIX=$(out)"
82 "NVCC_GENCODE=${flags.gencodeString}"
83- ]
84- ++ lib.optionals (cudaOlder "11.4") [
85- "CUDA_HOME=${cudatoolkit}"
86- "CUDA_LIB=${lib.getLib cudatoolkit}/lib"
87- "CUDA_INC=${lib.getDev cudatoolkit}/include"
88- ]
89- ++ lib.optionals (cudaAtLeast "11.4") [
90 "CUDA_HOME=${cuda_nvcc}"
91 "CUDA_LIB=${lib.getLib cuda_cudart}/lib"
92 "CUDA_INC=${lib.getDev cuda_cudart}/include"
···18 cuda_cudart
19 cuda_nvcc
20 cudaAtLeast
0021 flags
22 ;
23 # versions 2.26+ with CUDA 11.x error with
···52 which
53 autoAddDriverRunpath
54 python3
55+ cuda_nvcc
56+ ];
05758+ buildInputs = [
59+ cuda_nvcc # crt/host_config.h
60+ cuda_cudart
61+ ]
62+ # NOTE: CUDA versions in Nixpkgs only use a major and minor version. When we do comparisons
63+ # against other version, like below, it's important that we use the same format. Otherwise,
64+ # we'll get incorrect results.
65+ # For example, lib.versionAtLeast "12.0" "12.0.0" == false.
66+ ++ lib.optionals (cudaAtLeast "12.0") [ cuda_cccl ];
006768 env.NIX_CFLAGS_COMPILE = toString [ "-Wno-unused-function" ];
69···75 makeFlags = [
76 "PREFIX=$(out)"
77 "NVCC_GENCODE=${flags.gencodeString}"
000000078 "CUDA_HOME=${cuda_nvcc}"
79 "CUDA_LIB=${lib.getLib cuda_cudart}/lib"
80 "CUDA_INC=${lib.getDev cuda_cudart}/include"
···41 meta = with lib; {
42 homepage = "https://www.keybase.io/";
43 description = "Keybase official command-line utility and service";
044 platforms = platforms.linux ++ platforms.darwin;
45 maintainers = with maintainers; [
46 avaq
···41 meta = with lib; {
42 homepage = "https://www.keybase.io/";
43 description = "Keybase official command-line utility and service";
44+ mainProgram = "keybase";
45 platforms = platforms.linux ++ platforms.darwin;
46 maintainers = with maintainers; [
47 avaq
+1
pkgs/top-level/aliases.nix
···1762 retroarchBare = retroarch-bare; # Added 2024-11-23
1763 retroarchFull = retroarch-full; # Added 2024-11-23
1764 retroshare06 = retroshare;
01765 responsively-app = throw "'responsively-app' has been removed due to lack of maintainance upstream."; # Added 2025-06-25
1766 rftg = throw "'rftg' has been removed due to lack of maintenance upstream."; # Added 2024-12-04
1767 rigsofrods = rigsofrods-bin; # Added 2023-03-22
···1762 retroarchBare = retroarch-bare; # Added 2024-11-23
1763 retroarchFull = retroarch-full; # Added 2024-11-23
1764 retroshare06 = retroshare;
1765+ rewind-ai = throw "'rewind-ai' has been removed due to lack of of maintenance upstream"; # Added 2025-08-03
1766 responsively-app = throw "'responsively-app' has been removed due to lack of maintainance upstream."; # Added 2025-06-25
1767 rftg = throw "'rftg' has been removed due to lack of maintenance upstream."; # Added 2024-12-04
1768 rigsofrods = rigsofrods-bin; # Added 2023-03-22
···173 (
174 final: _:
175 {
176+ # Prevent missing attribute errors
177+ # NOTE(@connorbaker): CUDA 12.3 does not have a cuda_compat package; indeed, none of the release supports
178+ # Jetson devices. To avoid errors in the case that cuda_compat is not defined, we have a dummy package which
179+ # is always defined, but does nothing, will not build successfully, and has no platforms.
180+ cuda_compat = runCommand "cuda_compat" { meta.platforms = [ ]; } "false";
181 }
182 // lib.packagesFromDirectoryRecursive {
183 inherit (final) callPackage;