Files
emacs-org/notes/emacs-macos-build.org
Martin Sukany f81e1e8f0d update
2026-02-23 22:39:12 +01:00

7.8 KiB
Raw Blame History

Emacs macOS Build s macOS Zoom Accessibility

Návod na sestavení GNU Emacs pro macOS s patchem, který opravuje sledování kurzoru při zapnutém macOS Zoom ("Follow keyboard focus"). Postup vychází z reálné zkušenosti z buildu v únoru 2026.

Proč je to potřeba

macOS Zoom funguje jako magnifier přes celou obrazovku nebo v okně. Režim "Follow keyboard focus" by měl automaticky posouvat viewport za textovým kurzorem. Ve vanilla GNU Emacs to ale nefunguje.

Příčina: Emacs má vlastní NSView, který neimplementuje NSAccessibility protokol a hlavně nevolá UAZoomChangeFocus() z HIServices/UniversalAccess.h. Tuto funkci volají iTerm2 (PTYTextView.m) i Chromium (render_widget_host_view_mac.mm) a je to jediný spolehlivý způsob, jak Zoom přinutit sledovat kurzor v custom view.

Standardní NSAccessibility notifikace samy o sobě nestačí — Zoom je event-driven a potřebuje explicitní volání UAZoomChangeFocus() s aktuální pozicí kurzoru v souřadnicích AX obrazovky (origin vlevo nahoře, tzn. y-osa je otočená oproti Cocoa, kde origin je vlevo dole).

Patch je uložený v repozitáři martin/emacs-doom na Giteě: patches/0001-ns-implement-AXBoundsForRange-for-macOS-Zoom-cursor-.patch

Krok 1: Prerekvizity

Nejprve nainstaluj Xcode Command Line Tools (nutné pro kompilaci):

xcode-select --install

Pak nainstaluj závislosti přes Homebrew:

brew install autoconf libgmp texinfo pkg-config gnutls libxml2 jansson tree-sitter librsvg imagemagick

Pro native compilation (volitelné, výrazně rychlejší Emacs):

brew install libgccjit

Krok 2: Stažení zdrojového kódu Emacs

git clone https://github.com/emacs-mirror/emacs.git
cd emacs
git checkout emacs-31

Větev emacs-31 je aktuálně doporučená stable větev. Až bude k dispozici emacs-32, použij tu.

Krok 3: Aplikace accessibility patche

Stáhni config repozitář s patchem:

git clone https://git.apps.sukany.cz/martin/emacs-doom.git /tmp/emacs-doom-config

Aplikuj patch:

git am /tmp/emacs-doom-config/patches/0001-ns-implement-AXBoundsForRange-for-macOS-Zoom-cursor-.patch

Ověř, že patch byl aplikovaný:

grep "UAZoomChangeFocus" src/nsterm.m | head -3

Výsledkem by mělo být několik řádků s voláním UAZoomChangeFocus. Pokud grep nic nevrátí, patch se neaplikoval správně.

Co patch přidává do src/nsterm.m:

  • Volání UAZoomChangeFocus() po každém pohybu kurzoru — koordináty jsou přepočítány z Cocoa (origin vlevo dole) do AX prostoru (origin vlevo nahoře) ručním y-flipem: primaryH - y - height
  • NSAccessibilitySelectedTextChangedNotification — notifikace po pohybu kurzoru
  • NSAccessibilityFocusedUIElementChangedNotification — notifikace při zaměření okna
  • accessibilityBoundsForRange: — nové API (macOS 10.10+)
  • Fallback přes starší AXBoundsForRange pro starší verze
  • NSAccessibilityTextAreaRole pro EmacsView

Krok 4: Konfigurace

Spusť autogen a pak configure. Základní konfigurace (bez native compilation):

./autogen.sh
./configure \
  --with-ns \
  --with-tree-sitter \
  --with-gnutls \
  --with-xml2 \
  --with-json \
  --with-imagemagick \
  --with-rsvg \
  --with-mailutils \
  --without-x \
  --without-dbus \
  CFLAGS="-O2 -g3"

S native compilation (pokud máš libgccjit):

./configure \
  --with-ns \
  --with-native-compilation=aot \
  --with-tree-sitter \
  --with-gnutls \
  --with-xml2 \
  --with-json \
  --without-x \
  CFLAGS="-O2 -g3"

Krok 5: Build

make -j$(sysctl -n hw.ncpu)

Parametr -j$(sysctl -n hw.ncpu) použije všechna dostupná jádra. Build trvá přibližně 515 minut podle hardwaru.

Po dokončení build vytvoří nextstep/Emacs.app:

make install

Krok 6: Instalace

Přesuň Emacs.app do /Applications:

cp -r nextstep/Emacs.app /Applications/Emacs.app

Vytvoř wrapper script. Pozor: použij wrapper script, ne symlink. Symlink nefunguje správně — Emacs počítá cesty k Lisp souborům z argv[0], a přes resolved symlink je najde špatně. Projeví se to chybami jako:

Warning: arch-dependent data dir 'Contents/MacOS/libexec/': No such file or directory
Warning: Lisp directory 'Contents/Resources/lisp': No such file or directory

Správné řešení — wrapper script:

sudo tee /usr/local/bin/emacs > /dev/null << 'EOF'
#!/bin/sh
exec /Applications/Emacs.app/Contents/MacOS/Emacs "$@"
EOF
sudo chmod +x /usr/local/bin/emacs

Ověření:

which emacs
emacs --version

Výstup which emacs musí být /usr/local/bin/emacs.

Krok 7: Accessibility permission

Po každém novém buildu (nový binární soubor) je potřeba znovu udělit oprávnění. Bez toho UAZoomChangeFocus() neovlivní Zoom viewport — volání proběhne, ale macOS ho ignoruje bez Accessibility přístupu.

Postup:

  1. Otevři System Settings → Privacy & Security → Accessibility
  2. Přidej /Applications/Emacs.app
  3. Zapni toggle vedle Emacs

Pokud Emacs v seznamu už je (ze starého buildu), odeber ho a přidej znovu — macOS identifikuje aplikace i podle binary hash a starý záznam neplatí.

Krok 8: Doom Emacs sync

Pokud používáš Doom Emacs, spusť sync po instalaci nového Emacsu:

~/.emacs.d/bin/doom sync

Pokud doom hlásí, že nenajde Emacs, zkontroluj:

which emacs

Musí vrátit /usr/local/bin/emacs. Pokud vrátí jinou cestu, je problém s PATH nebo chybí wrapper script.

Krok 9: Ověření Zoom funkcionality

Nastav Zoom v System Settings:

  1. System Settings → Accessibility → Zoom
  2. Zapni "Use keyboard shortcut to zoom" nebo "Use scroll gesture with modifier keys to zoom"
  3. Zoom style: Full Screen nebo Window (obojí funguje)
  4. Klikni na "Advanced…" → záložka "Zoom Follows the Cursor"
  5. Nastav "Zoom follows: Keyboard focus"

Otevři Emacs a začni psát. Zoom viewport by měl automaticky sledovat textový kurzor při každém pohybu (šipky, PageUp/Down, přechod mezi buffery).

Řešení problémů

Zoom nesleduje kurzor

Nejčastější příčiny jsou dvě. Za prvé, chybí Accessibility permission — viz Krok 7. Za druhé, patch nebyl správně aplikovaný. Ověření:

grep "UAZoomChangeFocus" /Applications/Emacs.app/Contents/MacOS/../../../src/nsterm.m 2>/dev/null || \
  echo "Zkontroluj zdrojový kód nebo přelož znovu"

Nebo v build adresáři:

grep "UAZoomChangeFocus" src/nsterm.m | wc -l

Pokud výsledek je 0, patch chybí. Aplikuj znovu a přelož.

Build selže na nsterm.m

Zkontroluj, zda jsou nainstalované Xcode Command Line Tools:

xcode-select -p

Pokud cesta neexistuje nebo vrátí chybu, spusť xcode-select --install znovu.

doom sync hlásí "emacs not found"

Zkontroluj wrapper script:

cat /usr/local/bin/emacs

Soubor musí existovat a obsahovat exec /Applications/Emacs.app/Contents/MacOS/Emacs "$@". Pokud neexistuje, viz Krok 6.

Chyby "libexec not found" nebo "lisp not found" při startu

Příčina je symlink místo wrapper scriptu. Zkontroluj:

ls -la /usr/local/bin/emacs

Pokud výstup ukazuje -> (symlink), smaž ho a vytvoř wrapper script podle Kroku 6.

Reference