about summary refs log tree commit diff
path: root/pkgs/build-support/setup-hooks/wrap-gapps-hook/default.nix
blob: 3c5199be31322c2db76c521967dc1a301055fce7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
{ stdenv
, lib
, makeSetupHook
, makeWrapper
, gobject-introspection
, isGraphical ? true
, gtk3
, librsvg
, dconf
, callPackage
, wrapGAppsHook
, targetPackages
}:

makeSetupHook {
  name = "wrap-gapps-hook";
  propagatedBuildInputs = [
    # We use the wrapProgram function.
    makeWrapper
  ] ++ lib.optionals isGraphical [
    # TODO: remove this, packages should depend on GTK explicitly.
    gtk3

    librsvg
  ];

  # depsTargetTargetPropagated will essentially be buildInputs when wrapGAppsHook is placed into nativeBuildInputs
  # the librsvg and gtk3 above should be removed but kept to not break anything that implicitly depended on its binaries
  depsTargetTargetPropagated = assert (lib.assertMsg (!targetPackages ? raw) "wrapGAppsHook must be in nativeBuildInputs"); lib.optionals isGraphical [
    # librsvg provides a module for gdk-pixbuf to allow rendering
    # SVG icons. Most icon themes are SVG-based and so are some
    # graphics in GTK (e.g. cross for closing window in window title bar)
    # so it is pretty much required for applications using GTK.
    librsvg

    # TODO: remove this, packages should depend on GTK explicitly.
    gtk3
  ] ++ lib.optionals (!stdenv.isDarwin) [
    # It is highly probable that a program will use GSettings,
    # at minimum through GTK file chooser dialogue.
    # Let’s add a GIO module for “dconf” GSettings backend
    # to avoid falling back to “memory” backend. This is
    # required for GSettings-based settings to be persisted.
    # Unfortunately, it also requires the user to have dconf
    # D-Bus service enabled globally (e.g. through a NixOS module).
    dconf.lib
  ];
  passthru = {
    tests = let
      sample-project = ./tests/sample-project;

      testLib = callPackage ./tests/lib.nix { };
      inherit (testLib) expectSomeLineContainingYInFileXToMentionZ;
    in rec {
      # Simple derivation containing a program and a daemon.
      basic = stdenv.mkDerivation {
        name = "basic";

        src = sample-project;

        strictDeps = true;
        nativeBuildInputs = [ wrapGAppsHook ];

        installFlags = [ "bin-foo" "libexec-bar" ];
      };

      # The wrapper for executable files should add path to dconf GIO module.
      basic-contains-dconf = let
        tested = basic;
      in testLib.runTest "basic-contains-dconf" (
        testLib.skip stdenv.isDarwin ''
          ${expectSomeLineContainingYInFileXToMentionZ "${tested}/bin/foo" "GIO_EXTRA_MODULES" "${dconf.lib}/lib/gio/modules"}
          ${expectSomeLineContainingYInFileXToMentionZ "${tested}/libexec/bar" "GIO_EXTRA_MODULES" "${dconf.lib}/lib/gio/modules"}
        ''
      );

      basic-contains-gdk-pixbuf = let
        tested = basic;
      in testLib.runTest "basic-contains-gdk-pixbuf" (
        testLib.skip stdenv.isDarwin ''
          ${expectSomeLineContainingYInFileXToMentionZ "${tested}/bin/foo" "GDK_PIXBUF_MODULE_FILE" "${lib.getLib librsvg}/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache"}
          ${expectSomeLineContainingYInFileXToMentionZ "${tested}/libexec/bar" "GDK_PIXBUF_MODULE_FILE" "${lib.getLib librsvg}/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache"}
        ''
      );

      # Simple derivation containing a gobject-introspection typelib.
      typelib-Mahjong = stdenv.mkDerivation {
        name = "typelib-Mahjong";

        src = sample-project;

        strictDeps = true;

        installFlags = [ "typelib-Mahjong" ];
      };

      # Simple derivation using a typelib.
      typelib-user = stdenv.mkDerivation {
        name = "typelib-user";

        src = sample-project;

        strictDeps = true;
        nativeBuildInputs = [
          gobject-introspection
          wrapGAppsHook
        ];

        buildInputs = [
          typelib-Mahjong
        ];

        installFlags = [ "bin-foo" "libexec-bar" ];
      };

      # Testing cooperation with gobject-introspection setup hook,
      # which should populate GI_TYPELIB_PATH variable with paths
      # to typelibs among the derivation’s dependencies.
      # The resulting GI_TYPELIB_PATH should be picked up by the wrapper.
      typelib-user-has-gi-typelib-path = let
        tested = typelib-user;
      in testLib.runTest "typelib-user-has-gi-typelib-path" ''
        ${expectSomeLineContainingYInFileXToMentionZ "${tested}/bin/foo" "GI_TYPELIB_PATH" "${typelib-Mahjong}/lib/girepository-1.0"}
        ${expectSomeLineContainingYInFileXToMentionZ "${tested}/libexec/bar" "GI_TYPELIB_PATH" "${typelib-Mahjong}/lib/girepository-1.0"}
      '';

      # Simple derivation containing a gobject-introspection typelib in lib output.
      typelib-Bechamel = stdenv.mkDerivation {
        name = "typelib-Bechamel";

        outputs = [ "out" "lib" ];

        src = sample-project;

        strictDeps = true;

        makeFlags = [
          "LIBDIR=${placeholder "lib"}/lib"
        ];

        installFlags = [ "typelib-Bechamel" ];
      };

      # Simple derivation using a typelib from non-default output.
      typelib-multiout-user = stdenv.mkDerivation {
        name = "typelib-multiout-user";

        src = sample-project;

        strictDeps = true;
        nativeBuildInputs = [
          gobject-introspection
          wrapGAppsHook
        ];

        buildInputs = [
          typelib-Bechamel
        ];

        installFlags = [ "bin-foo" "libexec-bar" ];
      };

      # Testing cooperation with gobject-introspection setup hook,
      # which should populate GI_TYPELIB_PATH variable with paths
      # to typelibs among the derivation’s dependencies,
      # even when they are not in default output.
      # The resulting GI_TYPELIB_PATH should be picked up by the wrapper.
      typelib-multiout-user-has-gi-typelib-path = let
        tested = typelib-multiout-user;
      in testLib.runTest "typelib-multiout-user-has-gi-typelib-path" ''
        ${expectSomeLineContainingYInFileXToMentionZ "${tested}/bin/foo" "GI_TYPELIB_PATH" "${typelib-Bechamel.lib}/lib/girepository-1.0"}
        ${expectSomeLineContainingYInFileXToMentionZ "${tested}/libexec/bar" "GI_TYPELIB_PATH" "${typelib-Bechamel.lib}/lib/girepository-1.0"}
      '';

      # Simple derivation that contains a typelib as well as a program using it.
      typelib-self-user = stdenv.mkDerivation {
        name = "typelib-self-user";

        src = sample-project;

        strictDeps = true;
        nativeBuildInputs = [
          gobject-introspection
          wrapGAppsHook
        ];

        installFlags = [ "typelib-Cow" "bin-foo" "libexec-bar" ];
      };

      # Testing cooperation with gobject-introspection setup hook,
      # which should add the path to derivation’s own typelibs
      # to GI_TYPELIB_PATH variable.
      # The resulting GI_TYPELIB_PATH should be picked up by the wrapper.
      # https://github.com/NixOS/nixpkgs/issues/85515
      typelib-self-user-has-gi-typelib-path = let
        tested = typelib-self-user;
      in testLib.runTest "typelib-self-user-has-gi-typelib-path" ''
        ${expectSomeLineContainingYInFileXToMentionZ "${tested}/bin/foo" "GI_TYPELIB_PATH" "${typelib-self-user}/lib/girepository-1.0"}
        ${expectSomeLineContainingYInFileXToMentionZ "${tested}/libexec/bar" "GI_TYPELIB_PATH" "${typelib-self-user}/lib/girepository-1.0"}
      '';
    };
  };
} ./wrap-gapps-hook.sh