diff --git a/crates/hammer-build/src/lib.rs b/crates/hammer-build/src/lib.rs index 6e615ca8..995ef5ea 100644 --- a/crates/hammer-build/src/lib.rs +++ b/crates/hammer-build/src/lib.rs @@ -220,7 +220,13 @@ pub fn build( // Recetas Cargo: vendoreamos las deps (red permitida en el fetch) para que el build sea // hermético `--offline` dentro del sandbox. Tras los patches, por si tocaron Cargo.toml/lock. - if matches!(detect_build_system(&src_tree), BuildSys::Cargo) { + // `cargo_vendor = true` fuerza esta rama en árboles POLÍGLOTAS, donde `detect_build_system` + // —que asume un sistema por árbol— eligió el de C. librsvg es el arquetipo: `configure.ac` gana + // por precedencia, pero su Makefile llama a `cargo build`, y sin vendoreo ese cargo sale a la + // red dentro del sandbox hermético. Ver `Source::cargo_vendor`. + if matches!(detect_build_system(&src_tree), BuildSys::Cargo) + || eff_recipe.source.cargo_vendor == Some(true) + { // El source se copia DENTRO del repo hammer (que es un workspace Cargo) ⇒ si el Cargo.toml // de la fuente NO declara su propio `[workspace]`, cargo cree que pertenece al workspace de // hammer y `cargo vendor` aborta. Inyectamos un `[workspace]` vacío para aislarla. SÓLO si @@ -229,7 +235,13 @@ pub fn build( // por receta. Ver memoria 'cargo-recipe crate suelto'. ensure_cargo_workspace_isolation(&src_tree)?; // Extractor de workspaces (Etapa G): si el root es virtual, resuelve `-p ` del bin. - inject_cargo_package_selector(&mut eff_recipe, &src_tree); + // SÓLO cuando el árbol ES una receta Cargo. En un políglota (`cargo_vendor = true`) el + // producto lo arma el sistema de build de C —que llama a cargo con sus propios argumentos— + // y meterle un `-p` a los flags de la receta sería inyectar una opción de Cargo en un + // `./configure`. Acá el forzado pide vendoreo, nada más. + if matches!(detect_build_system(&src_tree), BuildSys::Cargo) { + inject_cargo_package_selector(&mut eff_recipe, &src_tree); + } tracing::info!("cargo: vendoreando deps para build offline"); fetch::vendor_cargo_deps( &src_tree, diff --git a/crates/hammer-core/src/recipe.rs b/crates/hammer-core/src/recipe.rs index d565e54f..b21c8957 100644 --- a/crates/hammer-core/src/recipe.rs +++ b/crates/hammer-core/src/recipe.rs @@ -66,6 +66,19 @@ pub struct Source { /// `.cargo/config.toml` que emite `cargo vendor` ya apunta al dir que se le pasa. #[serde(default, skip_serializing_if = "Option::is_none")] pub cargo_vendor_dir: Option, + /// Fuerza el vendoreo cargo aunque el árbol NO se detecte como `BuildSys::Cargo`. + /// + /// Existe porque `detect_build_system` asume **un** sistema de build por árbol, y hay proyectos + /// que genuinamente tienen dos: C por fuera, Rust por dentro. El arquetipo es librsvg —trae + /// `configure.ac` Y `Cargo.toml`, y autotools gana por precedencia—, pero su `Makefile` invoca + /// `cargo build`. Sin vendoreo ese cargo intenta salir a la red DENTRO del sandbox hermético y + /// el build muere. Es un patrón, no una excepción: cada vez hay más GNOME así. + /// + /// No cambia qué se construye, sólo de dónde salen las deps —el `Cargo.lock` del source es el + /// que fija las versiones— así que **no entra al ArtifactHash**, igual que `cargo_vendor_dir`. + /// Es lo que permite prenderla en una receta ya sellada sin re-hashearla. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub cargo_vendor: Option, #[serde(default)] pub patches: Vec, } @@ -732,6 +745,34 @@ expected_output = "b3:deadbeef" ); } + #[test] + fn cargo_vendor_roundtripea_y_no_afecta_el_hash() { + // `cargo_vendor` decide DE DÓNDE salen las deps de Cargo (registro vs. `vendor/` local), no + // CUÁLES: eso lo fija el `Cargo.lock` del source, que ya está bajo el hash de la fuente. Por + // eso no entra a `hash_inputs`, igual que `cargo_vendor_dir` — y por eso se puede prender en + // una receta YA SELLADA para destrabar su build offline sin re-hashear nada aguas abajo. + let sin = Recipe::from_toml(SAMPLE).unwrap(); + let mut con = sin.clone(); + con.source.cargo_vendor = Some(true); + assert_eq!( + sin.hash_inputs(&[]).unwrap(), + con.hash_inputs(&[]).unwrap(), + "cargo_vendor NO debe entrar en hash_inputs" + ); + // Y roundtripea por TOML: si se perdiera al serializar, el forzado se apagaría solo en + // cualquier flujo que reescriba la receta. + let r = Recipe::from_toml(&con.to_toml().unwrap()).unwrap(); + assert_eq!(r.source.cargo_vendor, Some(true)); + // Ausente sigue siendo ausente (no `Some(false)`), que es lo que mantiene el TOML limpio. + assert_eq!( + Recipe::from_toml(&sin.to_toml().unwrap()) + .unwrap() + .source + .cargo_vendor, + None + ); + } + #[test] fn slots_round_trip_y_no_afectan_el_hash() { // H4b: el bloque `slots` declara TOPOLOGÍA (qué toca / de qué depende), no identidad ⇒ diff --git a/recipes/incoming-gnome/ibus.toml b/recipes/incoming-gnome/ibus.toml new file mode 100644 index 00000000..6b26ef4b --- /dev/null +++ b/recipes/incoming-gnome/ibus.toml @@ -0,0 +1,107 @@ +# ibus 1.5.34 — el bus de métodos de entrada (teclados de chino/japonés/coreano, emoji, Unicode). +# De acá sale el typelib `IBus-1.0`. +# +# POR QUÉ ENTRA, y es el caso más claro de la tanda: gnome-shell lo importa desde JavaScript **sin +# condicional** (`js/misc/dependencies.js`: `import 'gi://IBus?version=1.0'`), aunque el usuario no +# use ningún método de entrada. El panel de teclado del shell habla con ibus siempre. Dep de RUNTIME +# invisible al grafo de build — el mismo patrón que AccountsService, Gdm, Geoclue y GWeather. +# +# LO QUE SE CONSTRUYE ES LA LIBRERÍA Y EL BUS, NO EL ESCRITORIO DE ibus. Casi todos los +# `--disable-*` de abajo apagan piezas que dependen de cosas que esta distro no tiene y que el shell +# no consulta: +# --disable-gtk2/3/4 los módulos de método de entrada para GTK. GTK3 no está en el +# corpus (decisión de X11-al-tacho) y el de GTK4 no hace falta: +# GTK4 habla `text-input` de Wayland directo con el compositor. +# ⚠ OJO CON EL TEXTO DE AYUDA DE UPSTREAM: dice `--enable-gtk4` +# y `--enable-wayland`, lo que sugiere que están APAGADAS por +# defecto. No lo están: `enable_gtk4=yes` y `enable_wayland=yes` +# son los defaults reales (configure.ac:277 y :299). Sin +# `--disable-gtk4` explícito el configure corta pidiendo gtk4. +# La ayuda miente; el default manda. +# +# ⚠ `--enable-wayland` VA PRENDIDA, y no por gusto. Empezó apagada —el módulo Wayland es para que el +# demonio de ibus hable con un compositor, y el shell implementa `text-input` por su cuenta— pero con +# `--disable-wayland` el build MUERE igual: `tools/main.c` incluye `` y llama +# `wl_display_connect`/`wl_display_disconnect` **sin ningún `#ifdef`** (:1260), mientras que el +# `WAYLAND_LIBS` que resolvería esos símbolos sólo se agrega si la opción está encendida. Es un bug +# de upstream en su propia configuración «sin Wayland». Prenderla es más honesto que parchear el +# `tools/`: esta distro ES Wayland. Arrastra `libxkbcommon`, que su PKG_CHECK pide junto a +# `wayland-client`. +# --disable-xim el servidor XIM. Es X11 puro. +# --disable-setup `ibus-setup`, una GUI en Python+GTK3. +# --disable-python2 / --disable-python-library / --disable-dbus-python-check +# bindings de Python 2. No hay Python 2 y no va a haber. +# --disable-dconf --enable-memconf ibus guarda su configuración en dconf por defecto; dconf no +# está en el corpus (ya lo esquivó gdm por la misma razón). +# `memconf` es el backend EN MEMORIA que trae upstream para +# exactamente este caso: la config no persiste entre sesiones, +# que para un escritorio sin métodos de entrada configurados es +# la diferencia entre nada y nada. +# --disable-systemd-services acá PID1 es arje-zero. +# --disable-appindicator pide dbusmenu-glib/dbusmenu-gtk3 (bandeja legacy de Ubuntu). +# --disable-libnotify sirve para que el DEMONIO avise «se cambió el método de +# entrada» por notificación de escritorio. libnotify no está en +# el corpus, y las notificaciones del escritorio las sirve el +# propio gnome-shell. +# --disable-engine el motor `simple` (mapas de teclado de teclas muertas). Va +# junto con emoji-dict: son datos y lógica de método de entrada, +# no la librería. +# --disable-emoji-dict el diccionario de emoji se compila desde los XML de CLDR y +# `/usr/share/unicode/emoji`, datos que no están en el corpus. +# Se pierde el selector de emoji de ibus, no el typelib. +# --disable-unicode-dict su hermano: el índice de nombres de caracteres se compila desde +# los ficheros UCD (`NamesList.txt`, `Blocks.txt` de +# `/usr/share/unicode/ucd`). Apagar emoji-dict NO lo apaga —son +# dos opciones distintas, y el configure aborta por la segunda +# después de pasar la primera. +# --disable-tests --disable-gtk-doc --disable-vala +# +# Las comprobaciones de X11/XFixes y de libevdev/libudev son BLANDAS en el configure.ac +# (:778 y :785 no abortan, sólo definen un condicional), así que no hace falta apagarlas ni +# satisfacerlas: se resuelven en "no" solas. +# +# ══ LA DEP QUE NO SE VE VENIR: `x11-compose-data` ══════════════════════════════════════════════ +# ibus COMPILA la tabla de teclas muertas de X11 dentro de libibus. `gen-internal-compose-table` +# (src/gencomposetable.c:70) lee un fichero `Compose` en tiempo de build y lo convierte en un +# GResource que entra en `ibusresources.c`; ese paso es INCONDICIONAL en su Makefile.am:310 y no hay +# `--disable-` que lo evite. Sin datos el build muere con +# `Failed to open file "/X11/locale/en/Compose"`. +# +# Los datos viven en el tarball de libX11 —por historia, no por necesidad técnica— así que hay una +# receta aparte, `x11-compose-data`, que extrae SÓLO los ficheros de locale y no compila una línea +# de X11. Es la tensión de un escritorio Wayland-only con un mundo Unix cuya tabla de composición +# sigue publicándose dentro de X11, y queda escrita ahí. +# +# También pide `iso-codes` (nombres de idioma para el selector de método de entrada), que ya estaba. +# +# ISLA DINÁMICA: el typelib nombra `libibus-1.0.so.5` y gjs la dlopea. +name = "ibus" +version = "1.5.34" + +[source] +tarball = "https://github.com/ibus/ibus/releases/download/1.5.34/ibus-1.5.34.tar.gz" +sha256 = "12a72210ce5250f8a66df562a75e034e67b2bce74c4df2983dc86d1154894943" + +[build] +compiler = "zig-cc" +target = "x86_64-linux-musl" +link = "dynamic" + +[build.phases] +configure = ''' +set -e +PKG_CONFIG_PATH=/usr/lib/pkgconfig ./configure --prefix=/usr \ + --enable-introspection --enable-memconf \ + --disable-gtk2 --disable-gtk3 --disable-gtk4 --enable-wayland \ + --disable-xim --disable-dconf \ + --disable-setup --disable-python2 --disable-python-library \ + --disable-dbus-python-check --disable-systemd-services \ + --disable-appindicator --disable-libnotify --disable-engine \ + --disable-emoji-dict --disable-unicode-dict --disable-tests \ + --disable-gtk-doc --disable-vala --disable-nls +''' +compile = "make" +install = "DESTDIR=/out make install" + +[deps] +build = ["make", "pkgconf", "python3", "py3-setuptools", "gobject-introspection", "gi-foreign-girs", "glib", "glib-introspected", "iso-codes", "x11-compose-data", "wayland", "wayland-protocols", "libxkbcommon", "dbus-shared", "libffi", "pcre2", "zlib-shared", "expat"] diff --git a/recipes/incoming-gnome/librsvg.toml b/recipes/incoming-gnome/librsvg.toml new file mode 100644 index 00000000..ca75168f --- /dev/null +++ b/recipes/incoming-gnome/librsvg.toml @@ -0,0 +1,78 @@ +# librsvg 2.58.5 — el renderizador de SVG de GNOME, escrito en Rust. De acá sale el typelib `Rsvg-2.0`. +# +# POR QUÉ ENTRA: gnome-shell lo importa desde JavaScript sin condicional +# (`js/misc/dependencies.js`: `import 'gi://Rsvg?version=2.0'`). Es lo que dibuja los iconos +# simbólicos del panel y los fondos vectoriales. Dep de RUNTIME del shell, invisible a su grafo de +# build. +# +# ══ POR QUÉ 2.58 Y NO 2.59+, que es lo que shippea GNOME 48 ═════════════════════════════════════ +# En 2.59 librsvg cambió a **meson + cargo-c**, y `cargo-cbuild` (el binario de lu-zero/cargo-c) no +# está en el corpus. Empaquetarlo no es una receta más: cargo-c ENLAZA el crate `cargo`, que arrastra +# libgit2, libssh2, libcurl y openssl como `*-sys`. Es una campaña propia, y por un binario que sólo +# corre en el constructor. +# +# 2.58.5 es la última de la serie autotools + `cargo build` plano, y produce **el mismo `Rsvg-2.0`** +# —la ABI del typelib no se movió—, así que el shell no nota la diferencia. Es el mismo criterio que +# ya se aplicó a gnome-desktop 44.5 en esta cola: la versión correcta es la que cierra la cadena, no +# la más nueva. Cuando cargo-c exista, subir es cambiar dos líneas. +# +# ══ LA PERILLA NUEVA DEL LAB: `cargo_vendor = true` ═════════════════════════════════════════════ +# librsvg es POLÍGLOTA — `configure.ac` Y `Cargo.toml` en la misma raíz— y `detect_build_system` +# asume un sistema por árbol: autotools gana por precedencia. Pero el `Makefile` invoca +# `cargo build`, y dentro del sandbox hermético ese cargo no tiene red ⇒ el build moría intentando +# bajar el registro. La perilla fuerza el vendoreo (que ocurre en el fetch, donde SÍ hay red) sin +# tocar la detección. No entra al ArtifactHash: decide de dónde salen las deps, no cuáles —eso lo +# fija el `Cargo.lock` del tarball, que ya está bajo el sha256 de la fuente. +# +# `CARGO_NET_OFFLINE=true` cierra el círculo: sin él cargo intentaría igual la red antes de mirar el +# `.cargo/config.toml` vendoreado en algunos caminos. +# +# ══ `LIBS=-lunwind`: LA DEUDA DEL UNWINDER, PAGADA ═════════════════════════════════════════════ +# Sin esto el build muere al linkear el binario temporal de la introspección: +# +# ld.lld: error: undefined reference: _Unwind_DeleteException +# >>> referenced by ./.libs/librsvg-2.so (disallowed by --no-allow-shlib-undefined) +# +# **No es de librsvg: es de la `std` de rustc**, que trae landing pads de unwinding y espera el +# runtime que en glibc vive en `libgcc_s`. Es exactamente la deuda que el corpus arrastra desde hace +# tiempo —«las 12 recetas Rust de la lista de matar-gcc son UN problema, no 12: falta un runtime de +# unwinding»— y el remedio resulta estar a mano: **zig empaqueta la libunwind de LLVM**, y exporta +# los `_Unwind_*` que hacen falta (verificado con `nm` sobre el `libunwind.a` de su caché). O sea que +# no hay que traer libgcc: alcanza con pedirle a zig el suyo. +# +# Va por `LIBS` y no por `LDFLAGS` a propósito: autotools pone `LIBS` al FINAL de la línea de enlace, +# que es donde tiene que ir una librería que resuelve símbolos indefinidos. En `LDFLAGS` iría antes +# de los objetos y el linker la descartaría por no tener nada pendiente todavía. +# +# ══ ALCANCE ════════════════════════════════════════════════════════════════════════════════════ +# `--disable-pixbuf-loader`: el loader SVG de gdk-pixbuf necesita correr +# `gdk-pixbuf-query-loaders` y reescribir el `loaders.cache` del sistema — un efecto sobre OTRO +# paquete, que en un store direccionable por contenido no se puede hacer desde acá. El shell no lo +# usa: carga SVG por `imports.gi.Rsvg`, no por GdkPixbuf. +# `--disable-gtk-doc`: gtk-doc no está en el corpus. +# +# ISLA DINÁMICA: el typelib nombra `librsvg-2.so.2` y gjs la dlopea. +name = "librsvg" +version = "2.58.5" + +[source] +tarball = "https://download.gnome.org/sources/librsvg/2.58/librsvg-2.58.5.tar.xz" +sha256 = "224233a0e347d38c415f15a49f0e0885313e3ecc18f3192055f9304dd2f3a27a" +cargo_vendor = true + +[build] +compiler = "zig-cc" +target = "x86_64-linux-musl" +link = "dynamic" + +[build.phases] +configure = ''' +set -e +PKG_CONFIG_PATH=/usr/lib/pkgconfig LIBS=-lunwind ./configure --prefix=/usr \ + --disable-gtk-doc --disable-pixbuf-loader --enable-introspection --disable-vala +''' +compile = "CARGO_NET_OFFLINE=true make" +install = "CARGO_NET_OFFLINE=true DESTDIR=/out make install" + +[deps] +build = ["make", "pkgconf", "python3", "py3-setuptools", "gobject-introspection", "gi-foreign-girs", "glib", "glib-introspected", "gdk-pixbuf", "cairo-shared", "pango", "harfbuzz", "fribidi", "freetype-shared", "fontconfig-shared", "libxml2-shared", "libpng-shared", "pixman", "expat", "libffi", "pcre2", "zlib-shared"] diff --git a/recipes/incoming-gnome/x11-compose-data.toml b/recipes/incoming-gnome/x11-compose-data.toml new file mode 100644 index 00000000..a7e92628 --- /dev/null +++ b/recipes/incoming-gnome/x11-compose-data.toml @@ -0,0 +1,76 @@ +# x11-compose-data — la base de secuencias Compose de X11, y NADA de X11. +# +# QUÉ ES: los ficheros `/usr/share/X11/locale/…` que definen las teclas muertas y las combinaciones +# de `Multi_key` (` a '` → `á`). Son **datos**, no código: 5192 líneas de reglas para +# `en_US.UTF-8`. Viven en el tarball de libX11 porque históricamente X11 fue quien las mantuvo, no +# porque necesiten X11 para existir. +# +# POR QUÉ LAS NECESITA UNA DISTRO SIN X11, y es una tensión real que conviene dejar escrita: **ibus +# las compila DENTRO de libibus**. Su `gen-internal-compose-table` (src/gencomposetable.c:70) lee un +# fichero `Compose` en tiempo de build y lo convierte en `compose/sequences--endian`, que +# entra como GResource en `ibusresources.c`. Ese paso NO es opcional en su Makefile.am:310 — no hay +# `--disable-` que lo evite. Sin datos, el build de ibus muere con +# `Failed to open file "/X11/locale/en/Compose"`. +# +# O sea: el escritorio es Wayland-only por decisión, pero la tabla de teclas muertas del mundo Unix +# sigue publicándose dentro de libX11. Empaquetar esos datos NO reintroduce X11: no hay una sola +# línea de código, ni un `.so`, ni una dependencia. Es el mismo criterio que `iso-codes`. +# +# CÓMO SE GENERAN: los ficheros del tarball son `.pre` y hay que pasarlos por el preprocesador de C. +# La receta REPRODUCE la regla de upstream (`cpprules.in`) tal cual, en vez de improvisar: +# · `cpp -undef -traditional -DWCHAR32=1` — `RAWCPP $(RAWCPPFLAGS) $(CPP_FILES_FLAGS)`. +# · el `CPP_SED_MAGIC`, copiado literal. Traduce `XCOMM` a `#` con sed y no con `-DXCOMM=XCOMM` +# —el comentario de upstream explica que ese truco no funciona en todos los preprocesadores—, +# borra las marcas de línea de cpp, sustituye `X11_LOCALEDATADIR` por la ruta real y colapsa los +# `@@` finales en barras invertidas. +# Verificado: la salida son 5192 líneas con 2337 secuencias de teclas muertas, sintaxis intacta. +# +# SÓLO en_US.UTF-8. Es la que ibus busca (`sys_langs[] = { "en_US.UTF-8", "en_US", "en" }`) y la que +# todas las demás locales incluyen por `include "%L"`. Traer las ~180 locales sería traer el árbol +# de i18n de X11 entero para que nadie lo lea. +# +# `locale.dir` no es decorativo: el configure de ibus decide `X11_LOCALEDATADIR` comprobando que +# EXISTA (configure.ac:394). Sin él cae a un `$(datadir)` sin expandir y el define queda en +# `"/X11/locale"`, que es exactamente el error de arriba. +name = "x11-compose-data" +version = "1.8.13" + +[source] +tarball = "https://gitlab.freedesktop.org/xorg/lib/libx11/-/archive/libX11-1.8.13/libx11-libX11-1.8.13.tar.gz" +sha256 = "d210291f5cd974e5029cce4bde0fc1b8bfc0ce88b8530ea6ba4b1fcf141506ab" + +[build] +compiler = "zig-cc" +target = "x86_64-linux-musl" +link = "dynamic" + +[build.phases] +configure = "true" +compile = "true" +install = ''' +set -e +LOCALEDIR=/usr/share/X11/locale +mkdir -p "/out$LOCALEDIR/en_US.UTF-8" +# La regla de upstream, literal (cpprules.in): cpp crudo + el CPP_SED_MAGIC. +gen() { + cpp -undef -traditional -DWCHAR32=1 < "$1" | LC_CTYPE=C sed \ + -e '/^\# *[0-9][0-9]* *.*$/d' \ + -e '/^\#line *[0-9][0-9]* *.*$/d' \ + -e '/^[ ]*XCOMM$/s/XCOMM/\#/' \ + -e '/^[ ]*XCOMM[^a-zA-Z0-9_]/s/XCOMM/\#/' \ + -e '/^[ ]*XHASH/s/XHASH/\#/' \ + -e "s,X11_LOCALEDATADIR,$LOCALEDIR,g" \ + -e '/\@\@$/s/\@\@$/\\/' \ + -e '/^$/d' > "$2" +} +gen nls/en_US.UTF-8/Compose.pre "/out$LOCALEDIR/en_US.UTF-8/Compose" +gen nls/en_US.UTF-8/XLC_LOCALE.pre "/out$LOCALEDIR/en_US.UTF-8/XLC_LOCALE" +gen nls/locale.dir.pre "/out$LOCALEDIR/locale.dir" +gen nls/compose.dir.pre "/out$LOCALEDIR/compose.dir" +gen nls/locale.alias.pre "/out$LOCALEDIR/locale.alias" +cp nls/en_US.UTF-8/XI18N_OBJS "/out$LOCALEDIR/en_US.UTF-8/XI18N_OBJS" +wc -l "/out$LOCALEDIR/en_US.UTF-8/Compose" +''' + +[deps] +build = ["make", "pkgconf"] diff --git a/scripts/gnome/hydrate-gnome.sh b/scripts/gnome/hydrate-gnome.sh index f7f821b5..7d2e3dbd 100755 --- a/scripts/gnome/hydrate-gnome.sh +++ b/scripts/gnome/hydrate-gnome.sh @@ -32,7 +32,14 @@ else recipes/incoming-gnome/gnome-shell.toml recipes/incoming-gnome/accountsservice.toml # imports.gi.AccountsService recipes/incoming-gnome/gi-foreign-typelibs.toml # DBus-1.0/cairo-1.0, que Gdk y Atspi incluyen - recipes/incoming-gnome/libgdm.toml # imports.gi.Gdm (js/misc/dependencies.js) + # El resto sale de `js/misc/dependencies.js` del shell — la lista donde DECLARA qué typelibs + # exige al arrancar. Cerrarlas de una evita el bucle de «arrancar, ver qué falta, rehacer imagen». + recipes/incoming-gnome/libgdm.toml # imports.gi.Gdm + recipes/incoming-gnome/geoclue.toml # imports.gi.Geoclue + recipes/incoming-gnome/libgweather.toml # imports.gi.GWeather + recipes/incoming-gnome/upower.toml # imports.gi.UPowerGlib + recipes/incoming-gnome/librsvg.toml # imports.gi.Rsvg + recipes/incoming-gnome/ibus.toml # imports.gi.IBus ) fi