1{ config
2, lib
3, stdenv
4, fetchurl
5, fetchpatch
6, gettext
7, meson
8, ninja
9, pkg-config
10, perl
11, python3
12, libiconv, zlib, libffi, pcre2, libelf, gnome, libselinux, bash, gnum4, gtk-doc, docbook_xsl, docbook_xml_dtd_45, libxslt
13# use util-linuxMinimal to avoid circular dependency (util-linux, systemd, glib)
14, util-linuxMinimal ? null
15, buildPackages
16
17# this is just for tests (not in the closure of any regular package)
18, coreutils, dbus, libxml2, tzdata
19, desktop-file-utils, shared-mime-info
20, darwin
21# update script
22, runCommand, git, coccinelle
23}:
24
25assert stdenv.isLinux -> util-linuxMinimal != null;
26
27# TODO:
28# * Make it build without python
29# Problem: an example (test?) program needs it.
30# Possible solution: disable compilation of this example somehow
31# Reminder: add 'sed -e 's@python2\.[0-9]@python@' -i
32# $out/bin/gtester-report' to postInstall if this is solved
33/*
34 * Use --enable-installed-tests for GNOME-related packages,
35 and use them as a separately installed tests runned by Hydra
36 (they should test an already installed package)
37 https://wiki.gnome.org/GnomeGoals/InstalledTests
38 * Support org.freedesktop.Application, including D-Bus activation from desktop files
39*/
40let
41 # Some packages don't get "Cflags" from pkg-config correctly
42 # and then fail to build when directly including like <glib/...>.
43 # This is intended to be run in postInstall of any package
44 # which has $out/include/ containing just some disjunct directories.
45 flattenInclude = ''
46 for dir in "''${!outputInclude}"/include/*; do
47 cp -r "$dir"/* "''${!outputInclude}/include/"
48 rm -r "$dir"
49 ln -s . "$dir"
50 done
51 ln -sr -t "''${!outputInclude}/include/" "''${!outputInclude}"/lib/*/include/* 2>/dev/null || true
52 '';
53
54 buildDocs = stdenv.hostPlatform == stdenv.buildPlatform && !stdenv.hostPlatform.isStatic;
55in
56
57stdenv.mkDerivation (finalAttrs: {
58 pname = "glib";
59 version = "2.74.1";
60
61 src = fetchurl {
62 url = "mirror://gnome/sources/glib/${lib.versions.majorMinor finalAttrs.version}/glib-${finalAttrs.version}.tar.xz";
63 sha256 = "CrmBYY0dtHhF5WQXsNfBI/gaNCeyuck/Wkb/W7uWSWQ=";
64 };
65
66 patches = lib.optionals stdenv.isDarwin [
67 ./darwin-compilation.patch
68 ] ++ lib.optionals stdenv.hostPlatform.isMusl [
69 ./quark_init_on_demand.patch
70 ./gobject_init_on_demand.patch
71 ] ++ [
72 ./glib-appinfo-watch.patch
73 ./schema-override-variable.patch
74
75 # Add support for the GNOME’s default terminal emulator.
76 # https://gitlab.gnome.org/GNOME/glib/-/issues/2618
77 ./gnome-console-support.patch
78 # Do the same for Pantheon’s terminal emulator.
79 ./elementary-terminal-support.patch
80
81 # GLib contains many binaries used for different purposes;
82 # we will install them to different outputs:
83 # 1. Tools for desktop environment ($bin)
84 # * gapplication (non-darwin)
85 # * gdbus
86 # * gio
87 # * gio-launch-desktop (symlink to $out)
88 # * gsettings
89 # 2. Development/build tools ($dev)
90 # * gdbus-codegen
91 # * gio-querymodules
92 # * glib-compile-resources
93 # * glib-compile-schemas
94 # * glib-genmarshal
95 # * glib-gettextize
96 # * glib-mkenums
97 # * gobject-query
98 # * gresource
99 # * gtester
100 # * gtester-report
101 # 3. Tools for desktop environment that cannot go to $bin due to $out depending on them ($out)
102 # * gio-launch-desktop
103 ./split-dev-programs.patch
104
105 # Disable flaky test.
106 # https://gitlab.gnome.org/GNOME/glib/-/issues/820
107 ./skip-timer-test.patch
108
109 # Fix infinite loop (e.g. in gnome-keyring)
110 # https://github.com/NixOS/nixpkgs/pull/197754#issuecomment-1312805358
111 # https://gitlab.gnome.org/GNOME/glib/-/merge_requests/3039
112 (fetchpatch {
113 url = "https://gitlab.gnome.org/GNOME/glib/-/commit/2a36bb4b7e46f9ac043561c61f9a790786a5440c.patch";
114 sha256 = "b77Hxt6WiLxIGqgAj9ZubzPWrWmorcUOEe/dp01BcXA=";
115 })
116 ];
117
118 outputs = [ "bin" "out" "dev" "devdoc" ];
119
120 setupHook = ./setup-hook.sh;
121
122 buildInputs = [
123 libelf
124 finalAttrs.setupHook
125 pcre2
126 ] ++ lib.optionals (!stdenv.hostPlatform.isWindows) [
127 bash gnum4 # install glib-gettextize and m4 macros for other apps to use
128 ] ++ lib.optionals stdenv.isLinux [
129 libselinux
130 util-linuxMinimal # for libmount
131 ] ++ lib.optionals stdenv.isDarwin (with darwin.apple_sdk.frameworks; [
132 AppKit Carbon Cocoa CoreFoundation CoreServices Foundation
133 ]) ++ lib.optionals buildDocs [
134 # Note: this needs to be both in buildInputs and nativeBuildInputs. The
135 # Meson gtkdoc module uses find_program to look it up (-> build dep), but
136 # glib's own Meson configuration uses the host pkg-config to find its
137 # version (-> host dep). We could technically go and fix this in glib, add
138 # pkg-config to depsBuildBuild, but this would be a futile exercise since
139 # Meson's gtkdoc integration does not support cross compilation[1] anyway
140 # and this derivation disables the docs build when cross compiling.
141 #
142 # [1] https://github.com/mesonbuild/meson/issues/2003
143 gtk-doc
144 ];
145
146 strictDeps = true;
147
148 nativeBuildInputs = [
149 meson
150 ninja
151 pkg-config
152 perl
153 python3
154 gettext
155 ] ++ lib.optionals buildDocs [
156 gtk-doc
157 docbook_xsl
158 docbook_xml_dtd_45
159 libxml2
160 libxslt
161 ];
162
163 propagatedBuildInputs = [ zlib libffi gettext libiconv ];
164
165 mesonFlags = [
166 # Avoid the need for gobject introspection binaries in PATH in cross-compiling case.
167 # Instead we just copy them over from the native output.
168 "-Dgtk_doc=${lib.boolToString buildDocs}"
169 "-Dnls=enabled"
170 "-Ddevbindir=${placeholder "dev"}/bin"
171 ] ++ lib.optionals (!stdenv.isDarwin) [
172 "-Dman=true" # broken on Darwin
173 ];
174
175 NIX_CFLAGS_COMPILE = toString [
176 "-Wno-error=nonnull"
177 # Default for release buildtype but passed manually because
178 # we're using plain
179 "-DG_DISABLE_CAST_CHECKS"
180 ];
181
182 postPatch = ''
183 chmod +x gio/tests/gengiotypefuncs.py
184 patchShebangs gio/tests/gengiotypefuncs.py
185 chmod +x docs/reference/gio/concat-files-helper.py
186 patchShebangs docs/reference/gio/concat-files-helper.py
187 patchShebangs glib/gen-unicode-tables.pl
188 patchShebangs glib/tests/gen-casefold-txt.py
189 patchShebangs glib/tests/gen-casemap-txt.py
190
191 # Needs machine-id, comment the test
192 sed -e '/\/gdbus\/codegen-peer-to-peer/ s/^\/*/\/\//' -i gio/tests/gdbus-peer.c
193 sed -e '/g_test_add_func/ s/^\/*/\/\//' -i gio/tests/gdbus-address-get-session.c
194 # All gschemas fail to pass the test, upstream bug?
195 sed -e '/g_test_add_data_func/ s/^\/*/\/\//' -i gio/tests/gschema-compile.c
196 # Cannot reproduce the failing test_associations on hydra
197 sed -e '/\/appinfo\/associations/d' -i gio/tests/appinfo.c
198 # Needed because of libtool wrappers
199 sed -e '/g_subprocess_launcher_set_environ (launcher, envp);/a g_subprocess_launcher_setenv (launcher, "PATH", g_getenv("PATH"), TRUE);' -i gio/tests/gsubprocess.c
200 '' + lib.optionalString stdenv.hostPlatform.isWindows ''
201 substituteInPlace gio/win32/meson.build \
202 --replace "libintl, " ""
203 '';
204
205 postConfigure = ''
206 patchShebangs gio/gdbus-2.0/codegen/gdbus-codegen gobject/glib-{genmarshal,mkenums}
207 '';
208
209 DETERMINISTIC_BUILD = 1;
210
211 postInstall = ''
212 moveToOutput "share/glib-2.0" "$dev"
213 substituteInPlace "$dev/bin/gdbus-codegen" --replace "$out" "$dev"
214 sed -i "$dev/bin/glib-gettextize" -e "s|^gettext_dir=.*|gettext_dir=$dev/share/glib-2.0/gettext|"
215
216 # This file is *included* in gtk3 and would introduce runtime reference via __FILE__.
217 sed '1i#line 1 "glib-${finalAttrs.version}/include/glib-2.0/gobject/gobjectnotifyqueue.c"' \
218 -i "$dev"/include/glib-2.0/gobject/gobjectnotifyqueue.c
219 for i in $bin/bin/*; do
220 moveToOutput "share/bash-completion/completions/''${i##*/}" "$bin"
221 done
222 for i in $dev/bin/*; do
223 moveToOutput "share/bash-completion/completions/''${i##*/}" "$dev"
224 done
225 '' + lib.optionalString (!buildDocs) ''
226 cp -r ${buildPackages.glib.devdoc} $devdoc
227 '';
228
229 # Move man pages to the same output as their binaries (needs to be
230 # done after preFixupHooks which moves man pages too - in
231 # _multioutDocs)
232 postFixup = ''
233 for i in $dev/bin/*; do
234 moveToOutput "share/man/man1/''${i##*/}.1.*" "$dev"
235 done
236 '';
237
238 checkInputs = [ tzdata desktop-file-utils shared-mime-info ];
239
240 preCheck = lib.optionalString finalAttrs.doCheck or config.doCheckByDefault or false ''
241 export LD_LIBRARY_PATH="$NIX_BUILD_TOP/glib-${finalAttrs.version}/glib/.libs''${LD_LIBRARY_PATH:+:}$LD_LIBRARY_PATH"
242 export TZDIR="${tzdata}/share/zoneinfo"
243 export XDG_CACHE_HOME="$TMP"
244 export XDG_RUNTIME_HOME="$TMP"
245 export HOME="$TMP"
246 export XDG_DATA_DIRS="${desktop-file-utils}/share:${shared-mime-info}/share"
247 export G_TEST_DBUS_DAEMON="${dbus.daemon}/bin/dbus-daemon"
248 export PATH="$PATH:$(pwd)/gobject"
249 echo "PATH=$PATH"
250 '';
251
252 separateDebugInfo = stdenv.isLinux;
253
254 passthru = rec {
255 gioModuleDir = "lib/gio/modules";
256
257 makeSchemaDataDirPath = dir: name: "${dir}/share/gsettings-schemas/${name}";
258 makeSchemaPath = dir: name: "${makeSchemaDataDirPath dir name}/glib-2.0/schemas";
259 getSchemaPath = pkg: makeSchemaPath pkg pkg.name;
260 getSchemaDataDirPath = pkg: makeSchemaDataDirPath pkg pkg.name;
261
262 tests.withChecks = finalAttrs.finalPackage.overrideAttrs (_: { doCheck = true; });
263
264 inherit flattenInclude;
265 updateScript = gnome.updateScript {
266 packageName = "glib";
267 versionPolicy = "odd-unstable";
268 };
269 /*
270 can be used as part of an update script to automatically create a patch
271 hardcoding the path of all gsettings schemas in C code.
272 For example:
273 passthru = {
274 hardcodeGsettingsPatch = glib.mkHardcodeGsettingsPatch {
275 inherit src;
276 glib-schema-to-var = {
277 ...
278 };
279 };
280
281 updateScript =
282 let
283 updateSource = ...;
284 patch = _experimental-update-script-combinators.copyAttrOutputToFile "evolution-ews.hardcodeGsettingsPatch" ./hardcode-gsettings.patch;
285 in
286 _experimental-update-script-combinators.sequence [
287 updateSource
288 patch
289 ];
290 };
291 }
292 takes as input a mapping from schema path to variable name.
293 For example `{ "org.gnome.evolution" = "EVOLUTION_SCHEMA_PATH"; }`
294 hardcodes looking for `org.gnome.evolution` into `@EVOLUTION_SCHEMA_PATH@`.
295 All schemas must be listed.
296 */
297 mkHardcodeGsettingsPatch = { src, glib-schema-to-var }:
298 runCommand
299 "hardcode-gsettings.patch"
300 {
301 inherit src;
302 nativeBuildInputs = [
303 git
304 coccinelle
305 python3 # For patch script
306 ];
307 }
308 ''
309 unpackPhase
310 cd "''${sourceRoot:-.}"
311 set -x
312 cp ${builtins.toFile "glib-schema-to-var.json" (builtins.toJSON glib-schema-to-var)} ./glib-schema-to-var.json
313 git init
314 git add -A
315 spatch --sp-file "${./hardcode-gsettings.cocci}" --dir . --in-place
316 git diff > "$out"
317 '';
318 };
319
320 meta = with lib; {
321 description = "C library of programming buildings blocks";
322 homepage = "https://www.gtk.org/";
323 license = licenses.lgpl21Plus;
324 maintainers = teams.gnome.members ++ (with maintainers; [ lovek323 raskin ]);
325 platforms = platforms.unix;
326
327 longDescription = ''
328 GLib provides the core application building blocks for libraries
329 and applications written in C. It provides the core object
330 system used in GNOME, the main loop implementation, and a large
331 set of utility functions for strings and common data structures.
332 '';
333 };
334})