Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.jylhis.com/llms.txt

Use this file to discover all available pages before exploring further.

Nix Build System

Jotain uses Nix for reproducible Emacs builds with fine-grained control over compile options. The source of nixpkgs is the revision pinned in flake.lock by default; both default.nix and emacs.nix read it directly via fetchTarball, so non-flake nix-build consumers get the same pin. Pass --arg pkgs '<nixpkgs>' or override pkgs to use a different one.

Two-Layer Architecture

emacs.nix

The core build expression. It takes pkgs.emacs-git (or pkgs.emacs-macport for the macport variant) from nix-community/emacs-overlay and calls .override { ... } with every upstream build flag exposed as a file-level argument. The overlay is added in flake.nix/devenv.nix because Emacs 31 is not yet shipped in nixpkgs. Supported:
  • Source variants: mainline (emacs-overlay’s emacs-git = current master, default), git (alias for mainline), unstable (emacs-unstable, latest tagged release), macport (emacs-macport, jdtsmith/emacs-mac fork), igc (emacs-igc, the feature/igc3 Memory Pool System incremental GC branch).
  • GUI toolkits: GTK3, pgtk (pure GTK for Wayland), NS (Cocoa/NeXTstep on macOS), Motif, Athena, X11, or no GUI at all (noGui = true).
  • Compilation: native compilation (libgccjit AOT, default when the build platform can execute the host), compressed install, C sources for find-function-C-source, srcRepo (run autoreconf on git-based sources).
  • Image formats: WebP (default), Cairo (X11 default), optionally ImageMagick.
  • Libraries: tree-sitter, SQLite3, Jansson (off — Emacs 30+ ships JSON), dbus, selinux, gpm, ALSA, ACL, mailutils, systemd, GLib networking.
  • Darwin patches: optional system-appearance, round-undecorated-frame, and fix-window-role patches fetched from nix-giant/nix-darwin-emacs, applied via overrideAttrs.

Cache-parity invariant

emacs.nix is written so that every argument default matches the corresponding default in emacs-overlay’s emacs-git derivation (which mirrors upstream nixpkgs’ make-emacs.nix). As long as that holds,
import ./emacs.nix {}                  # mainline
import ./emacs.nix { noGui = true; }   # any standard override
produces the exact store path of pkgs.emacs-git(.override { ... }), so the nix-community.cachix.org (and project jylhis) binary caches hit and nothing recompiles from source. Only the unstable / igc / macport variants and the Darwin patch flags are expected to diverge — those paths run through overrideAttrs and intentionally bust the cache. Verify after any change to defaults:
nix-instantiate --eval --strict -E '
  let lock = builtins.fromJSON (builtins.readFile ./flake.lock);
      n = lock.nodes.nixpkgs.locked;
      ov = lock.nodes.emacs-overlay.locked;
      nixpkgs = fetchTarball {
        url = "https://github.com/${n.owner}/${n.repo}/archive/${n.rev}.tar.gz";
        sha256 = n.narHash;
      };
      overlay = fetchTarball {
        url = "https://github.com/${ov.owner}/${ov.repo}/archive/${ov.rev}.tar.gz";
        sha256 = ov.narHash;
      };
      pkgs = import nixpkgs { overlays = [ (import overlay) ]; };
  in (import ./emacs.nix {}).outPath == pkgs.emacs-git.outPath'

default.nix

The distribution layer. It imports emacs.nix (forwarding every argument it does not consume itself) and, when withTreeSitterGrammars is true (default), wraps the result with emacsPackagesFor emacs |> withPackages (epkgs: [ epkgs.treesit-grammars.with-all-grammars ]). The resulting Emacs loads all ~275 grammars out of the box; early-init.el wires them in via TREE_SITTER_DIR / treesit-extra-load-path.

Key Build Options

OptionDefaultDescription
variant"mainline"Emacs source variant — mainline / git / unstable / macport / igc
withTreeSitterGrammarstrue(default.nix) include all tree-sitter grammars
noGuifalseTerminal only — --without-x --without-ns
withPgtkfalsePure GTK (Wayland) — --with-pgtk
withGTK3withPgtk && !noGuiGTK3 toolkit — --with-x-toolkit=gtk3
withNativeCompilationautolibgccjit AOT compilation
withTreeSittertrueBuilt-in tree-sitter support
withSystemdLinux--with-systemd (journal support)
withSystemAppearancePatchfalse(Darwin) add ns-system-appearance hooks
withRoundUndecoratedFramePatchfalse(Darwin) rounded borderless frames
withFixWindowRolePatchfalse(Darwin, Emacs 30 only) fix NSAccessibility role for tiling WMs
rev / hashnullPin a specific commit for git / unstable / igc / macport variants
See emacs.nix for the complete argument list and defaults.

IGC Variant

The igc variant builds Emacs’s feature/igc3 branch, which replaces the default mark-and-sweep garbage collector with the Memory Pool System. emacs.nix adds --with-mps=yes to configureFlags and pkgs.mps to buildInputs when variant = "igc", so the only manual step is providing the source hash on first build.

Git Variants

For git, unstable, and igc, emacs.nix fetches from https://git.savannah.gnu.org/git/emacs.git via fetchgit. The first build reports the correct hash; re-run with --argstr hash "sha256-..." (or edit the gitMeta attrset). postPatch substitutes the recorded revision into lisp/loadup.el so emacs-repository-get-version returns the expected value without a .git directory in the build tree. On aarch64-linux, git builds automatically get --enable-check-lisp-object-type added to avoid segfaults.
Last modified on May 21, 2026