1{ config
2, lib
3, stdenv
4, fetchurl
5, fetchpatch
6, gettext
7, meson
8, ninja
9, pkg-config
10, perl
11, python3
12, python3Packages
13, libiconv, zlib, libffi, pcre2, elfutils, gnome, libselinux, bash, gnum4, libxslt
14, docutils, gi-docgen
15# use util-linuxMinimal to avoid circular dependency (util-linux, systemd, glib)
16, util-linuxMinimal ? null
17, buildPackages
18
19# this is just for tests (not in the closure of any regular package)
20, coreutils, dbus, tzdata
21, desktop-file-utils, shared-mime-info
22, darwin
23, makeHardcodeGsettingsPatch
24, testers
25, gobject-introspection
26, mesonEmulatorHook
27, withIntrospection ?
28 stdenv.hostPlatform.emulatorAvailable buildPackages &&
29 lib.meta.availableOn stdenv.hostPlatform gobject-introspection &&
30 stdenv.hostPlatform.isLittleEndian == stdenv.buildPlatform.isLittleEndian
31}:
32
33assert stdenv.isLinux -> util-linuxMinimal != null;
34
35let
36 # Some packages don't get "Cflags" from pkg-config correctly
37 # and then fail to build when directly including like <glib/...>.
38 # This is intended to be run in postInstall of any package
39 # which has $out/include/ containing just some disjunct directories.
40 flattenInclude = ''
41 for dir in "''${!outputInclude}"/include/*; do
42 cp -r "$dir"/* "''${!outputInclude}/include/"
43 rm -r "$dir"
44 ln -s . "$dir"
45 done
46 ln -sr -t "''${!outputInclude}/include/" "''${!outputInclude}"/lib/*/include/* 2>/dev/null || true
47 '';
48
49 gobject-introspection' = buildPackages.gobject-introspection.override {
50 propagateFullGlib = false;
51 # Avoid introducing cairo, which enables gobjectSupport by default.
52 x11Support = false;
53 };
54
55 librarySuffix = if (stdenv.hostPlatform.extensions.library == ".so") then "2.0.so.0"
56 else if (stdenv.hostPlatform.extensions.library == ".dylib") then "2.0.0.dylib"
57 else if (stdenv.hostPlatform.extensions.library == ".a") then "2.0.a"
58 else if (stdenv.hostPlatform.extensions.library == ".dll") then "2.0-0.dll"
59 else "2.0-0.lib";
60in
61
62stdenv.mkDerivation (finalAttrs: {
63 pname = "glib";
64 version = "2.80.4";
65
66 src = fetchurl {
67 url = "mirror://gnome/sources/glib/${lib.versions.majorMinor finalAttrs.version}/glib-${finalAttrs.version}.tar.xz";
68 hash = "sha256-JOApxd/JtE5Fc2l63zMHipgnxIk4VVAEs7kJb6TqA08=";
69 };
70
71 patches = lib.optionals stdenv.isDarwin [
72 ./darwin-compilation.patch
73 # FIXME: remove when https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4088 is merged and is in the tagged release
74 (fetchpatch {
75 url = "https://gitlab.gnome.org/GNOME/glib/-/commit/9d0988ca62ee96e09aa76abbd65ff192cfce6858.patch";
76 hash = "sha256-JrR3Ba6L+3M0Nt8DgHmPG8uKtx7hOgUp7np08ATIzjA=";
77 })
78 ] ++ lib.optionals stdenv.hostPlatform.isMusl [
79 ./quark_init_on_demand.patch
80 ./gobject_init_on_demand.patch
81 ] ++ [
82 # This patch lets GLib's GDesktopAppInfo API watch and notice changes
83 # to the Nix user and system profiles. That way, the list of available
84 # applications shown by the desktop environment is immediately updated
85 # when the user installs or removes any
86 # (see <https://issues.guix.gnu.org/35594>).
87
88 # It does so by monitoring /nix/var/nix/profiles (for changes to the system
89 # profile) and /nix/var/nix/profiles/per-user/USER (for changes to the user
90 # profile) as well as /etc/profiles/per-user (for chanes to the user
91 # environment profile) and crawling their share/applications sub-directory when
92 # changes happen.
93 ./glib-appinfo-watch.patch
94
95 ./schema-override-variable.patch
96
97 # Add support for Pantheon’s terminal emulator.
98 ./elementary-terminal-support.patch
99
100 # GLib contains many binaries used for different purposes;
101 # we will install them to different outputs:
102 # 1. Tools for desktop environment ($bin)
103 # * gapplication (non-darwin)
104 # * gdbus
105 # * gio
106 # * gio-launch-desktop (symlink to $out)
107 # * gsettings
108 # 2. Development/build tools ($dev)
109 # * gdbus-codegen
110 # * gio-querymodules
111 # * glib-compile-resources
112 # * glib-compile-schemas
113 # * glib-genmarshal
114 # * glib-gettextize
115 # * glib-mkenums
116 # * gobject-query
117 # * gresource
118 # * gtester
119 # * gtester-report
120 # 3. Tools for desktop environment that cannot go to $bin due to $out depending on them ($out)
121 # * gio-launch-desktop
122 ./split-dev-programs.patch
123
124 # Tell Meson to install gdb scripts next to the lib
125 # GDB only looks there and in ${gdb}/share/gdb/auto-load,
126 # and by default meson installs in to $out/share/gdb/auto-load
127 # which does not help
128 ./gdb_script.patch
129
130 # glib assumes that `RTLD_LOCAL` is defined to `0`, which is true on Linux and FreeBSD but not on Darwin.
131 ./gmodule-rtld_local.patch
132 ];
133
134 outputs = [ "bin" "out" "dev" "devdoc" ];
135
136 setupHook = ./setup-hook.sh;
137
138 buildInputs = [
139 finalAttrs.setupHook
140 pcre2
141 ] ++ lib.optionals (!stdenv.hostPlatform.isWindows) [
142 bash gnum4 # install glib-gettextize and m4 macros for other apps to use
143 ] ++ lib.optionals (lib.meta.availableOn stdenv.hostPlatform elfutils) [
144 elfutils
145 ] ++ lib.optionals stdenv.isLinux [
146 libselinux
147 util-linuxMinimal # for libmount
148 ] ++ lib.optionals stdenv.isDarwin (with darwin.apple_sdk.frameworks; [
149 AppKit Carbon Cocoa CoreFoundation CoreServices Foundation
150 ]);
151
152 strictDeps = true;
153
154 depsBuildBuild = [
155 pkg-config # required to find native gi-docgen
156 ];
157
158 nativeBuildInputs = [
159 docutils # for rst2man, rst2html5
160 meson
161 ninja
162 pkg-config
163 perl
164 python3
165 python3Packages.packaging # mostly used to make meson happy
166 python3Packages.wrapPython # for patchPythonScript
167 gettext
168 libxslt
169 ] ++ lib.optionals withIntrospection [
170 gi-docgen
171 gobject-introspection'
172 ] ++ lib.optionals (withIntrospection && !stdenv.buildPlatform.canExecute stdenv.hostPlatform) [
173 mesonEmulatorHook
174 ];
175
176 propagatedBuildInputs = [ zlib libffi gettext libiconv ];
177
178 mesonFlags = [
179 "-Ddocumentation=true" # gvariant specification can be built without gi-docgen
180 "-Dnls=enabled"
181 "-Ddevbindir=${placeholder "dev"}/bin"
182 (lib.mesonEnable "introspection" withIntrospection)
183 # FIXME: Fails when linking target glib/tests/libconstructor-helper.so
184 # relocation R_X86_64_32 against hidden symbol `__TMC_END__' can not be used when making a shared object
185 "-Dtests=${lib.boolToString (!stdenv.hostPlatform.isStatic)}"
186 ] ++ lib.optionals (!lib.meta.availableOn stdenv.hostPlatform elfutils) [
187 "-Dlibelf=disabled"
188 ] ++ lib.optionals stdenv.isFreeBSD [
189 "-Db_lundef=false"
190 "-Dxattr=false"
191 ];
192
193 env.NIX_CFLAGS_COMPILE = toString [
194 "-Wno-error=nonnull"
195 # Default for release buildtype but passed manually because
196 # we're using plain
197 "-DG_DISABLE_CAST_CHECKS"
198 ];
199
200 postPatch = ''
201 patchShebangs glib/gen-unicode-tables.pl
202 patchShebangs glib/tests/gen-casefold-txt.py
203 patchShebangs glib/tests/gen-casemap-txt.py
204 patchShebangs tools/gen-visibility-macros.py
205 patchShebangs tests
206
207 # Needs machine-id, comment the test
208 sed -e '/\/gdbus\/codegen-peer-to-peer/ s/^\/*/\/\//' -i gio/tests/gdbus-peer.c
209 sed -e '/g_test_add_func/ s/^\/*/\/\//' -i gio/tests/gdbus-address-get-session.c
210 # All gschemas fail to pass the test, upstream bug?
211 sed -e '/g_test_add_data_func/ s/^\/*/\/\//' -i gio/tests/gschema-compile.c
212 # Cannot reproduce the failing test_associations on hydra
213 sed -e '/\/appinfo\/associations/d' -i gio/tests/appinfo.c
214 # Needed because of libtool wrappers
215 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
216 '' + lib.optionalString stdenv.hostPlatform.isWindows ''
217 substituteInPlace gio/win32/meson.build \
218 --replace "libintl, " ""
219 '';
220
221 postConfigure = ''
222 patchShebangs gio/gdbus-2.0/codegen/gdbus-codegen gobject/glib-{genmarshal,mkenums}
223 '';
224
225 DETERMINISTIC_BUILD = 1;
226
227 postInstall = ''
228 moveToOutput "share/glib-2.0" "$dev"
229 moveToOutput "share/glib-2.0/gdb" "$out"
230 substituteInPlace "$dev/bin/gdbus-codegen" --replace "$out" "$dev"
231 sed -i "$dev/bin/glib-gettextize" -e "s|^gettext_dir=.*|gettext_dir=$dev/share/glib-2.0/gettext|"
232
233 # This file is *included* in gtk3 and would introduce runtime reference via __FILE__.
234 sed '1i#line 1 "glib-${finalAttrs.version}/include/glib-2.0/gobject/gobjectnotifyqueue.c"' \
235 -i "$dev"/include/glib-2.0/gobject/gobjectnotifyqueue.c
236 for i in $bin/bin/*; do
237 moveToOutput "share/bash-completion/completions/''${i##*/}" "$bin"
238 done
239 for i in $dev/bin/*; do
240 moveToOutput "share/bash-completion/completions/''${i##*/}" "$dev"
241 done
242 '';
243
244 preFixup = lib.optionalString (!stdenv.hostPlatform.isStatic) ''
245 buildPythonPath ${python3Packages.packaging}
246 patchPythonScript "$dev/share/glib-2.0/codegen/utils.py"
247 '';
248
249 # Move man pages to the same output as their binaries (needs to be
250 # done after preFixupHooks which moves man pages too - in
251 # _multioutDocs)
252 postFixup = ''
253 for i in $dev/bin/*; do
254 moveToOutput "share/man/man1/''${i##*/}.1.*" "$dev"
255 done
256
257 # Cannot be in postInstall, otherwise _multioutDocs hook in preFixup will move right back.
258 moveToOutput "share/doc" "$devdoc"
259 '';
260
261 nativeCheckInputs = [ tzdata desktop-file-utils shared-mime-info ];
262
263 # Conditional necessary to break infinite recursion with passthru.tests
264 preCheck = lib.optionalString finalAttrs.finalPackage.doCheck or config.doCheckByDefault or false ''
265 export LD_LIBRARY_PATH="$NIX_BUILD_TOP/glib-${finalAttrs.version}/glib/.libs''${LD_LIBRARY_PATH:+:}$LD_LIBRARY_PATH"
266 export TZDIR="${tzdata}/share/zoneinfo"
267 export XDG_CACHE_HOME="$TMP"
268 export XDG_RUNTIME_HOME="$TMP"
269 export HOME="$TMP"
270 export XDG_DATA_DIRS="${desktop-file-utils}/share:${shared-mime-info}/share"
271 export G_TEST_DBUS_DAEMON="${dbus}/bin/dbus-daemon"
272
273 # pkg_config_tests expects a PKG_CONFIG_PATH that points to meson-private, wrapped pkg-config
274 # tries to be clever and picks up the wrong glib at the end.
275 export PATH="${buildPackages.pkg-config-unwrapped}/bin:$PATH:$(pwd)/gobject"
276 echo "PATH=$PATH"
277
278 # Our gobject-introspection patches make the shared library paths absolute
279 # in the GIR files. When running tests, the library is not yet installed,
280 # though, so we need to replace the absolute path with a local one during build.
281 # We are using a symlink that we will delete before installation.
282 mkdir -p $out/lib
283 ln -s $PWD/gobject/libgobject-${librarySuffix} $out/lib/libgobject-${librarySuffix}
284 ln -s $PWD/gio/libgio-${librarySuffix} $out/lib/libgio-${librarySuffix}
285 ln -s $PWD/glib/libglib-${librarySuffix} $out/lib/libglib-${librarySuffix}
286 '';
287
288 postCheck = ''
289 rm $out/lib/libgobject-${librarySuffix}
290 rm $out/lib/libgio-${librarySuffix}
291 rm $out/lib/libglib-${librarySuffix}
292 '';
293
294 separateDebugInfo = stdenv.isLinux;
295
296 passthru = rec {
297 gioModuleDir = "lib/gio/modules";
298
299 makeSchemaDataDirPath = dir: name: "${dir}/share/gsettings-schemas/${name}";
300 makeSchemaPath = dir: name: "${makeSchemaDataDirPath dir name}/glib-2.0/schemas";
301 getSchemaPath = pkg: makeSchemaPath pkg pkg.name;
302 getSchemaDataDirPath = pkg: makeSchemaDataDirPath pkg pkg.name;
303
304 tests = {
305 withChecks = finalAttrs.finalPackage.overrideAttrs (_: { doCheck = true; });
306 pkg-config = testers.testMetaPkgConfig finalAttrs.finalPackage;
307 };
308
309 inherit flattenInclude;
310 updateScript = gnome.updateScript {
311 packageName = "glib";
312 versionPolicy = "odd-unstable";
313 };
314
315 mkHardcodeGsettingsPatch =
316 {
317 src,
318 glib-schema-to-var,
319 }:
320 builtins.trace
321 "glib.mkHardcodeGsettingsPatch is deprecated, please use makeHardcodeGsettingsPatch instead"
322 (makeHardcodeGsettingsPatch {
323 inherit src;
324 schemaIdToVariableMapping = glib-schema-to-var;
325 });
326 };
327
328 meta = with lib; {
329 description = "C library of programming buildings blocks";
330 homepage = "https://gitlab.gnome.org/GNOME/glib";
331 license = licenses.lgpl21Plus;
332 maintainers = teams.gnome.members ++ (with maintainers; [ lovek323 raskin ]);
333 pkgConfigModules = [
334 "gio-2.0"
335 "gobject-2.0"
336 "gthread-2.0"
337 ];
338 platforms = platforms.unix ++ platforms.windows;
339
340 longDescription = ''
341 GLib provides the core application building blocks for libraries
342 and applications written in C. It provides the core object
343 system used in GNOME, the main loop implementation, and a large
344 set of utility functions for strings and common data structures.
345 '';
346 };
347})