Add a full-featured terminal Emacs 30.2
Replaces nothing: recipes/emacs-nox.sgl stays as it is. This is the same version built with the opposite intent. sqlite3, tree-sitter, zlib, dynamic modules and elisp threads are on, and JSON needs no dependency because Emacs 30 has it in-tree.
Verified by running the binary, not by reading configure output. emacs -nw starts in a real pty (TUI-FRAME=t COLS=80 LINES=23 DISPLAY=nil), and sqlite, JSON and zlib each do actual work rather than answering an availability predicate: a two-row table is created and selected back, a plist round-trips through json-serialize and json-parse-string, and 81 gzip bytes inflate to their original text. treesit-library-abi-version reports 14, matching the ABI measured directly against the built libtree-sitter.
libxml2 is switched OFF EXPLICITLY, and that is the finding rather than a preference. The seed's pkgconf 1.9.5 aborts on any .pc file with an empty dependency-list field, and libxml2 installs Requires: empty. Emacs looks for libxml2 through PKGCHECKMODULES, reads SIGABRT as "not present", and configure still exits 0 -- so the default would have produced an Emacs silently missing a requested feature. Saying --without-xml2 makes the definition state a fact.
The cause was isolated by running Emacs' own configure twice in a replica of the build environment, changing one variable: with LIBXML2CFLAGS and LIBXML2LIBS set, PKGCHECKMODULES skips pkg-config and detection succeeds. That fix cannot be written into the package, because those values need libxml2's store prefix and a phase argument has no way to name a dependency's path.
Native compilation is absent by decision, recorded in the module header.
channel.catalogue.sgl | 3 ++-
channel.catalogue.sgl.minisig | 6 +++---
channel.sgl | 3 ++-
objects/90fc3c5e9b0c35deada7f219417fb5d64f27d2cf88564c46ede646a7a3721a7e.sgl | 1 +
objects/d64a1058772a9536aabdd66610d6838730a5e3c47ce2d1f43e5995ce888b8cc2.sgl | 1 +
snapshot.sgl | 4 ++--
snapshot.sgl.minisig | 6 +++---
src/core/outputs.sgl | 17 +++++++++++++++--
src/core/packages/editors.sgl | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
9 files changed, 139 insertions(+), 13 deletions(-)channel.catalogue.sglmodified
(catalogue schema: 1 sequence: 4 snapshot: "core-stable@4:sha256:ea46962821ceb61bc8f331ee0eca5a4fd1db6650403ed2ba00e1c7352269e858" channel-source: "sha256:5db8e61c4c7e38a53a1d32bd0f73b9aa0b6cc372706586e6711b7a7e0daa303c" content-hash: "sha256:87d970255f4ce1cd9c93a4064cd6e2da80f8f46fbc3f7400e20b9dd1aaa2b784")(catalogue schema: 1 sequence: 6 snapshot: "core-stable@6:sha256:1ee737116d9669fa8d503baf5a275a12ccac79e2b7e1722ebd8260c6367ad963" channel-source: "sha256:30966b33315bb8383158afe41fb25a98790def2192caebb682be8b896acb0423" content-hash: "sha256:e96d244ea805692c9d018ac1c0ea041a9d36c57d84e1904e1814ba5fa269d982")(binding name: "core/binaryen" package: "sha256:014baf016eec17892f30a30847b070ffb09e397182d2ef50eda2ceb3fded2a58")(binding name: "core/emacs" package: "sha256:90fc3c5e9b0c35deada7f219417fb5d64f27d2cf88564c46ede646a7a3721a7e")(binding name: "core/libxml2" package: "sha256:cc4c7518170d4f5db3c72025a429c57c83e8d07244c06f922a0e2af3ffd9120c")(binding name: "core/ncurses" package: "sha256:e803a7f68e4a55eac49be30b3dc84855749037be91aa48ec7315f73dd5c0d1b3")(binding name: "core/sqlite" package: "sha256:39a80e18e85b9f228b147d47a3243c0276f639e30f72d841320abbeedc28900a")channel.catalogue.sgl.minisigmodified
untrusted comment: signature from minisign secret keyRUQ0HOFEHrNeRIL6qFa743en5litQy9WITcI7UTehPi1tbwuxJ6YzcpNWhBY6b9lKMK9TsHQ2z4Jg2AfD82SmMrMVZEXkQcpLgA=trusted comment: registry=pkg.usesigil.org path=/v1/channels/core-stable/channel.catalogue.sgl seq=508 ts=2026-07-30T19:20:00Z+p0luUXsem4c8uQOiUSClYPdIemnFULg3xgoLhPYSRhA0R+mnqdQ0Q6/BxXsChdw46h6wLbLNUl0J70VvvpODQ==RUQ0HOFEHrNeROHLSvMWtPQg4Lud+wHtDX/JNqsScgfMfXJBPt6oW9F+lVUZ0DLPxk1iGKI+fnePKp95Ge+CvlaDwOg3CiZuFAc=trusted comment: registry=pkg.usesigil.org path=/v1/channels/core-stable/channel.catalogue.sgl seq=512 ts=2026-07-30T20:10:00ZP5MBxqiLIfOxfjcU9I0+U8qNoIur5RNCXcOad5vU+nBo4tmuAB3QV8p9qiylihk3ZgbxUxGRuw66KMbrM6JrBw==channel.sglmodified
(channel-binding name: "core/libxml2" value: libxml2) (channel-binding name: "core/sqlite" value: sqlite) (channel-binding name: "core/tree-sitter" value: tree-sitter) (channel-binding name: "core/vim" value: vim))) (channel-binding name: "core/vim" value: vim) (channel-binding name: "core/emacs" value: emacs)))objects/90fc3c5e9b0c35deada7f219417fb5d64f27d2cf88564c46ede646a7a3721a7e.sgladded
(package-v1 name: "emacs" version: "30.2" source: (source location: "https://ftp.gnu.org/gnu/emacs/emacs-30.2.tar.xz" sha256: "b3f36f18a6dd2715713370166257de2fae01f9d38cfe878ced9b1e6ded5befd9") buildenv: "894ca74bdb03c25d79f00ce915bbe25c56eba192334963c69e1846e6c84526cb" dependencies: ("82b7de949e90992450f57ce5b4eb0cb3f1107d3731376dc19bd56c009bf38aad" "8695c98c7ed14c29bd12a3e4bc9d0287e1d55fccb25f568662909296d8e51781" "9625c2c1a633c79836e4ad7a13c2532af92b7b423ced098ca20d31c984e54818" "b575d0e29ea3f15262d850a4732a007779037f2ba55b67153738430eb91c8736" "e7026efe2fe0fc17c068cab9bad5277f9131f6fc4d379acd2bc7373477cbb9ce") phases: ((phase kind: configure args: ("--prefix=/out" "--disable-build-details" "--with-tree-sitter" "--with-modules" "--without-x" "--with-x-toolkit=no" "--without-xft" "--without-harfbuzz" "--without-libotf" "--without-m17n-flt" "--without-cairo" "--without-lcms2" "--without-gif" "--without-jpeg" "--without-png" "--without-rsvg" "--without-tiff" "--without-webp" "--without-xpm" "--without-xml2" "--without-dbus" "--without-gsettings" "--without-libsystemd" "--without-selinux" "--without-sound" "--without-gnutls" "--without-gpm" "--without-pop" "--without-mailutils") patches: ()) (phase kind: make args: () patches: ()) (phase kind: install args: () patches: ())) divergences: ((divergence file-glob: "libexec/emacs/*/*.pdmp" max-differing-bytes: 64)))objects/d64a1058772a9536aabdd66610d6838730a5e3c47ce2d1f43e5995ce888b8cc2.sgladded
(package-v1 name: "emacs" version: "30.2" source: (source location: "https://ftp.gnu.org/gnu/emacs/emacs-30.2.tar.xz" sha256: "b3f36f18a6dd2715713370166257de2fae01f9d38cfe878ced9b1e6ded5befd9") buildenv: "894ca74bdb03c25d79f00ce915bbe25c56eba192334963c69e1846e6c84526cb" dependencies: ("82b7de949e90992450f57ce5b4eb0cb3f1107d3731376dc19bd56c009bf38aad" "8695c98c7ed14c29bd12a3e4bc9d0287e1d55fccb25f568662909296d8e51781" "9625c2c1a633c79836e4ad7a13c2532af92b7b423ced098ca20d31c984e54818" "b575d0e29ea3f15262d850a4732a007779037f2ba55b67153738430eb91c8736" "e7026efe2fe0fc17c068cab9bad5277f9131f6fc4d379acd2bc7373477cbb9ce") phases: ((phase kind: configure args: ("--prefix=/out" "--disable-build-details" "--with-tree-sitter" "--with-modules" "--without-x" "--with-x-toolkit=no" "--without-xft" "--without-harfbuzz" "--without-libotf" "--without-m17n-flt" "--without-cairo" "--without-lcms2" "--without-gif" "--without-jpeg" "--without-png" "--without-rsvg" "--without-tiff" "--without-webp" "--without-xpm" "--without-dbus" "--without-gsettings" "--without-libsystemd" "--without-selinux" "--without-sound" "--without-gnutls" "--without-gpm" "--without-pop" "--without-mailutils") patches: ()) (phase kind: make args: () patches: ()) (phase kind: install args: () patches: ())) divergences: ((divergence file-glob: "libexec/emacs/*/*.pdmp" max-differing-bytes: 64)))snapshot.sglmodified
(snapshot schema: 1 id: "core-stable" sequence: 4 content-hash: "sha256:ea46962821ceb61bc8f331ee0eca5a4fd1db6650403ed2ba00e1c7352269e858")(snapshot schema: 1 id: "core-stable" sequence: 6 content-hash: "sha256:1ee737116d9669fa8d503baf5a275a12ccac79e2b7e1722ebd8260c6367ad963")(toolchain id: "toolchain/zig" version: "0.16.0" recipe: "sha256:5bc02f4c7abc6055b1f5fc37c57c4b063c18f9e3431ba2cab0cc9f30f313e33b" output: "sha256:70e49664a74374b48b51e6f3fdfbf437f6395d42509050588bd49abe52ba3d00")(pkg id: "core/packages/wasm" version: "0.1.0" recipe: "sha256:5db8e61c4c7e38a53a1d32bd0f73b9aa0b6cc372706586e6711b7a7e0daa303c")(pkg id: "core/packages/wasm" version: "0.1.0" recipe: "sha256:30966b33315bb8383158afe41fb25a98790def2192caebb682be8b896acb0423")snapshot.sgl.minisigmodified
untrusted comment: signature from minisign secret keyRUQ0HOFEHrNeRF9tOsiMdGpoFALsMi3+nIEREAcx885kaQmhwDAg2XDAHxM9PYJPzT5R0N+lQ9yeBqrvOLJ4YIFfTxvH9RcPjAk=trusted comment: registry=pkg.usesigil.org path=/v1/channels/core-stable/snapshot.sgl seq=507 ts=2026-07-30T19:20:00ZsybTz3/5QuEO+2YR1ETBbFjGm2goUuUQV0Hao9UNajzeWbrdNBpP90De+IBdgNEMBAR9JKHXj6aBzkFk8kVvAw==RUQ0HOFEHrNeREBz+oIIg15i/NHOqkih6ueihHoLK+0wbkvxG5HEnsw7Ae9qSoydHTi2Co3NfHoOCIMQhm4GcdmHXmJVOvicMAQ=trusted comment: registry=pkg.usesigil.org path=/v1/channels/core-stable/snapshot.sgl seq=511 ts=2026-07-30T20:10:00ZUwGJgmu86V+AU1hucEoCHoQCwoG8vTdcEbOLpLoCujv2mWMFD94xY5W1nU02PoRo9YJoFhMOdb90LDupgnPTBQ==src/core/outputs.sglmodified
;;; would let a dependency be an actual package binding.(define-library (core outputs) (import (sigil core)) (export zlib-output ncurses-output) (export zlib-output ncurses-output libxml2-output sqlite-output tree-sitter-output) (begin ;; core/zlib 1.3.1 ;; core/ncurses 6.6 (define ncurses-output "8695c98c7ed14c29bd12a3e4bc9d0287e1d55fccb25f568662909296d8e51781"))) "8695c98c7ed14c29bd12a3e4bc9d0287e1d55fccb25f568662909296d8e51781") ;; core/libxml2 2.13.5 (define libxml2-output "b575d0e29ea3f15262d850a4732a007779037f2ba55b67153738430eb91c8736") ;; core/sqlite 3.46.1 (define sqlite-output "9625c2c1a633c79836e4ad7a13c2532af92b7b423ced098ca20d31c984e54818") ;; core/tree-sitter 0.24.7 (define tree-sitter-output "82b7de949e90992450f57ce5b4eb0cb3f1107d3731376dc19bd56c009bf38aad")))src/core/packages/editors.sglmodified
(core outputs) (sigil env package) (sigil build external)) (export vim) (export vim emacs) (begin (define vim (package kind: 'make args: (list "VIMRCLOC=/out/share/vim" "VIMRUNTIMEDIR=/out/share/vim/vim91")) (external-phase kind: 'install)))) ;; A terminal Emacs that is actually worth using, as opposed to the ;; `emacs-nox` recipe in recipes/, which disabled essentially everything. ;; ;; Enabled here: ncurses, zlib decompression, libxml2 (shr/eww), sqlite3 ;; (org-roam and friends), tree-sitter (*-ts-mode), and dynamic modules. ;; JSON needs no dependency at all -- Emacs 30 has it in-tree at src/json.c, ;; so jansson, which Guix still lists for emacs-no-x, is not a dependency of ;; this version. ;; ;; DEPENDENCIES ARE A FLAT CLOSURE, NOT A GRAPH. The builder derives -I, ;; -L and PKG_CONFIG_PATH only from the entries listed here, so this list ;; must eventually name every transitive dependency, not just the direct ;; ones. With gnutls added that means nettle, gmp, libtasn1, libunistring ;; and p11-kit appear here too. See (core outputs). ;; ;; Deliberately absent, decided rather than forgotten: ;; * native compilation (libgccjit) -- means building GCC itself, which ;; needs a multi-stage bootstrap, arbitrary build commands and ;; per-package environment control. None of the five phase kinds can ;; express any of those. It is the largest performance win in the ;; target set and it is not reachable in this model. ;; * libxml2 -- BLOCKED BY A BUG IN THE PINNED SEED, not by choice. The ;; seed's pkgconf 1.9.5 aborts (SIGABRT, Zig pointer-overflow panic) on ;; any .pc file containing an EMPTY dependency-list field, and libxml2 ;; installs `Requires:` empty. Emacs finds libxml2 through ;; PKG_CHECK_MODULES, reads the crash as "not present", and CONFIGURE ;; STILL EXITS 0 -- so leaving this to the default would silently ;; produce an Emacs without a feature the definition asked for. Saying ;; --without-xml2 makes the absence a stated fact instead. ;; The remedy is known and was verified: setting LIBXML2_CFLAGS and ;; LIBXML2_LIBS makes PKG_CHECK_MODULES skip pkg-config entirely, and ;; detection then succeeds. It cannot be written here, because those ;; values need libxml2's own store prefix and **a phase argument has no ;; way to name a dependency's path** -- `replace-prefix` only rewrites ;; /out to the package's OWN prefix. Flip this back to the default the ;; day the seed's pkgconf is fixed. ;; * gnutls and gpm -- not yet ported; the flags below flip to ;; --with-gnutls / --with-gpm once they land. NOTE that gnutls is also ;; found via PKG_CHECK_MODULES, so it is exposed to the same seed bug if ;; its .pc or anything in its Requires chain has an empty field. (define emacs (package name: "emacs" version: "30.2" source: (external-source location: "https://ftp.gnu.org/gnu/emacs/emacs-30.2.tar.xz" sha256: "b3f36f18a6dd2715713370166257de2fae01f9d38cfe878ced9b1e6ded5befd9") buildenv: core-buildenv dependencies: (list ncurses-output zlib-output libxml2-output sqlite-output tree-sitter-output) ;; A portable dump is a memory image written once the build root is ;; known. external-normalize-build-root! pads build-root strings inside ;; outputs, but it cannot make a dump bit-identical across two runs, so ;; the bounded allowance the original recipe carried still earns its ;; place. It is a budget, not a blanket: anything outside *.pdmp, or ;; more than 64 bytes inside it, is still a hard determinism failure. divergences: (list (external-divergence file-glob: "libexec/emacs/*/*.pdmp" max-differing-bytes: 64)) phases: (list (external-phase kind: 'configure args: (list "--prefix=/out" ;; omit host name and build date from the ;; binary; this channel cares about ;; reproducibility more than about `M-x ;; emacs-version` naming a machine "--disable-build-details" ;; features we are deliberately turning ON "--with-tree-sitter" "--with-modules" ;; no window system "--without-x" "--with-x-toolkit=no" "--without-xft" "--without-harfbuzz" "--without-libotf" "--without-m17n-flt" "--without-cairo" "--without-lcms2" "--without-gif" "--without-jpeg" "--without-png" "--without-rsvg" "--without-tiff" "--without-webp" "--without-xpm" ;; blocked by the seed pkgconf bug above, not a ;; preference; stated so the build cannot ;; quietly differ from the definition "--without-xml2" ;; no system integration we cannot pin "--without-dbus" "--without-gsettings" "--without-libsystemd" "--without-selinux" "--without-sound" ;; not yet ported "--without-gnutls" "--without-gpm" ;; movemail: no Kerberos/Hesiod/mailutils here "--without-pop" "--without-mailutils")) (external-phase kind: 'make) (external-phase kind: 'install))))))