Emacs: Compilar Emacs en Linux Mint Vanessa

Referencias

Normalmente no me suelo complicar la vida compilando programas a menos que tenga unas ganas locas de probar algo y no haya más remedio, pero esta vez me dejé llevar.

Trás actualizar a Linux Mint 21 (Vanessa) decidí que ya era hora de probar Emacs con native compilation así que instale Emacs 28.1 desde el ppa de Kelleyk. La instalación no dió ningún problema pero al intentar configurar Emacs una de las primeras cosas que hice fué poner straight.el en lugar de Package y me dió el error:

Symbol's function definition is void: gv-setter

Y con este error falla totalmente la carga de mi fichero init.el.

El error puede comprobarse fácilmente con el comando: emacs -q --eval "(require 'gv)"

A la hora de ponerme a compilar estaba convencido de haber leido en internet que era un fallo del código en Emacs y que se corregía con la siguiente versión, pero a la hora de escribir esto ya no estoy tan seguro por que soy incapaz de encontrar la referencia.

En cualquier caso, decidí compilar Emacs 28.2 y estos son los pasos que seguí:

Preparando el terreno

Ajustamos nuestras preferencias de paquetes en Linux Mint (por ejemplo abriendo Synaptic) de forma que estén activados los orígenes de las fuentes del software (Source Code). Si lo haces con Synaptic se encargará de actualizar, de lo contrario asegurate de hacer un sudo apt update desde el terminal.

Instalamos las dependencias para la compilación con sudo apt build-dep pero también instalamos algunos programas a mayores:

1
2
sudo apt build-dep emacs && /
sudo apt install libgccjit0 libgccjit-11-dev libjansson4 libjansson-dev gnutls-bin

Los paquetes adicionales son para aprovechar todas las características del nuevo Emacs con native compilation, son necesarias para aprovechar todas las mejoras del rendimiento de Emacs.

También tenemos que descargar el código fuente de Emacs

Compilando el código fuente

Establecemos las variables para el compilador:

1
export CC=/usr/bin/gcc-11 && export CXX=/usr/bin/gcc-11

Si tienes dudas de cual es tu gcc, ejecuta:

1
2
3
4
$ which gcc
/usr/bin/gcc
$ ls -lha /usr/bin/gcc
/usr/bin/gcc ⇒ gcc-11
Advertencia
Si las variables de entorno CC y CCX no se especifican el script de configuración no va a poder encontrar muchas bibliotecas y dará errores del tipo error: ELisp native compiler was requested, but libgccjit was not found.

Ejecutamos el script autogen.sh, que creará un script configure específico para nuestro sistema.

Y procedemos con la configuración ejecutando:

1
./configure --with-native-compilation --prefix=/opt/emacs-28.2

La opción prefix no es necesaria, pero yo quiero tener controlado donde se instala esta versión compilada de Emacs, no quiero que se mezcle con los ficheros del sistema.

Como de momento no uso Emacs para gestionar mi correo puedo ignorar los warnings de movemail en cualquier caso ejecutando ./configure --help podemos ver todas las opciones disponibles. En general configure ve disponibles en el sistema las bibliotecas necesarias, se habilitan las opciones correspondientes, aunque --with-native-compilation es obligatorio especificarla.

Ahora lanzamos el proceso de compilación con

1
make -j$(nproc)

Este comando asigna todos los nucleos del sistema a la compilación, podemos asignar un número fijo si queremos (por ejemplo make -j2)

Una vez completada la compilación del programa sin errores, podemos probar nuestro Emacs recién compilado con ./src/emacs -q

También podemos comprobar que ya no tenemos el error de gv con el comando emacs -q —eval "(require 'gv)"

update-alternatives

Suponiendo que hemos instalado nuestra nueva versión de Emacs en /opt/emacs-28.2/. Tendremos que usar la utilidad de sistema update-alternatives para dejar nuestro nuevo Emacs accesible.

Si echamos un vistazo /opt/emacs-28.2/bin:

1
2
3
4
5
6
7
ls /opt/emacs-28.2/bin
.rwxr-xr-x root root 445 KB Tue Nov  1 17:08:00 2022 ctags
.rwxr-xr-x root root 199 KB Tue Nov  1 17:08:00 2022 ebrowse
lrwxrwxrwx root root  10 B  Tue Nov  1 17:08:01 2022 emacs ⇒ emacs-28.2
.rwxr-xr-x root root  24 MB Tue Nov  1 17:08:01 2022 emacs-28.2
.rwxr-xr-x root root 234 KB Tue Nov  1 17:08:00 2022 emacsclient
.rwxr-xr-x root root 441 KB Tue Nov  1 17:08:00 2022 etags

Veremos todos los programas ejecutables que hemos instalado al ejecutar el make install.

Tomemos como ejemplo el comando emacs, vamos a ver como funciona la llamada a emacs en nuestro sistema.

1
2
3
4
5
6
7
8
$ which emacs
/usr/bin/emacs

$ ls -lha /usr/bin/emacs
/usr/bin/emacs ⇒ /etc/alternatives/emacs

$ ls -lha /etc/alternatives/emacs
/etc/alternatives/emacs ⇒ /usr/bin/emacs28

El Emacs de nuestro sistema /usr/bin/emacs apunta en realidad a /etc/alternatives/emacs. A su vez /etc/alternatives/emacs apunta a /usr/bin/emacs28 (el que he instalado desde el PPA)

Podemos inspeccionar la configuración de update-alternatives con dos comandos: update-alternatives --config emacs y update-alternatives --display emacs. El primero no da mucha información por que sólo tenemos una alternativa definida para emacs (de momento). El segundo es más interesante:

1
2
3
4
5
6
7
8
$ update-alternatives --display emacs
emacs - auto mode
  link best version is /usr/bin/emacs28
  link currently points to /usr/bin/emacs28
  link emacs is /usr/bin/emacs
  slave emacs.1.gz is /usr/share/man/man1/emacs.1.gz
/usr/bin/emacs28 - priority 27
  slave emacs.1.gz: /usr/share/man/man1/emacs28.1.gz

Vamos a añadir nuestra nueva alternativa con prioridad 28:

1
2
sudo update-alternatives --install /usr/bin/emacs emacs /opt/emacs-28.2/bin/emacs-28.2 28 \
--slave /usr/share/man/man1/emacs.1.gz emacs.1.gz /opt/emacs-28.2/share/man/man1/emacs.1.gz

Ahora tendremos:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$ update-alternatives --display emacs
emacs - auto mode
  link best version is /opt/emacs28/bin/emacs-28.2
  link currently points to /opt/emacs28/bin/emacs-28.2
  link emacs is /usr/bin/emacs
  slave emacs.1.gz is /usr/share/man/man1/emacs.1.gz
/opt/emacs-28.2/bin/emacs-28.2 - priority 28
  slave emacs.1.gz: /opt/emacs-28.2/share/man/man1/emacs.1.gz
/usr/bin/emacs28 - priority 27
  slave emacs.1.gz: /usr/share/man/man1/emacs.1.gz

Si vemos todo los programas que tenemos disponibles en /opt/emacs-28.2 veremos que tenemos que actualizar las alternativas para emacsclient, tags, etagsyebrowse`.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
sudo update-alternatives --install /usr/bin/emacsclient emacsclient /opt/emacs-28.2/bin/emacsclient 28 \
--slave /usr/share/man/man1/emacsclient.1.gz emacsclient.1.gz /opt/emacs-28.2/share/man/man1/emacsclient.1.gz

sudo update-alternatives --install /usr/bin/ctags ctags /opt/emacs-28.2/bin/ctags 28 \
--slave /usr/share/man/man1/ctags.1.gz ctags.1.gz /opt/emacs-28.2/share/man/man1/ctags.1.gz

sudo update-alternatives --install /usr/bin/etags etags /opt/emacs-28.2/bin/etags 28 \
--slave /usr/share/man/man1/etags.1.gz etags.1.gz /opt/emacs-28.2/share/man/man1/etags.1.gz

sudo update-alternatives --install /usr/bin/ebrowse ebrowse /opt/emacs-28.2/bin/ebrowse 28 \
--slave /usr/share/man/man1/ebrowse.1.gz ebrose.1.gz /opt/emacs-28.2/share/man/man1/ebrowse.1.gz

Ficheros desktop

Ya casi hemos terminado, para finalizar solo tenemos que actualizar (o crear) ficheros .desktop que apunten a nuestro nuevo Emacs.

Podemos comprobar los ficheros .desktop existentes con:

1
2
3
4
5
6
$ ls -lha /usr/share/applications/*emacs*
.rw-r--r-- root root 440 B Tue May 17 05:05:27 2022 /usr/share/applications/emacs28.desktop
.rw-r--r-- root root 260 B Tue May 17 05:05:27 2022 /usr/share/applications/emacs28-mail.desktop
.rw-r--r-- root root 412 B Tue May 17 05:05:27 2022 /usr/share/applications/emacs28.desktop
.rw-r--r-- root root 643 B Tue May 17 05:05:27 2022 /usr/share/applications/emacsclient28-mail.desktop
.rw-r--r-- root root 826 B Tue May 17 05:05:27 2022 /usr/share/applications/emacsclient28.desktop

Tendremos que crear nuevas versiones de esos ficheros que apunten al Emacs recién instalado (o editar los existentes), por poner un ejemplo este es el fichero emacs-28.2.desktop resultado de modificar el emacs28.desktop:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
[Desktop Entry]
Name=Emacs-28.2
GenericName=Text Editor
Comment=Edit text
MimeType=text/english;text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++;
Exec=/opt/emacs-28.2/bin/emacs-28.2 %F
Icon=emacs28
Type=Application
Terminal=false
Categories=Development;TextEditor;
StartupNotify=true
StartupWMClass=Emacs

Hay que ver el resto de ficheros desktop y comprobar si necesitan modificaciones para funcionar sin problemas.

ACTUALIZACIÓN: Compilando emacs 29

Unas notas rápidas de los pasos seguidos para compilar Emacs 29.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# Recuerda que previamente hay que activar los origenes de software de Source Code
# Después de activarlos hacemos un update
sudo apt update


# Deberías tener instalado build-essential y git
# Ademas de algunas herramientas de compilación
sudo apt install build-essential git
sudo apt autoconf automake libtool


# Para tener las dependencias de Emacs instaladas hacemos un:
sudo apt build-dep emacs

# Averigua que versión de libgccjit instalar (yo tengo gcc-11 ahora mismo)
# gcc --version

# Instalamos algunas dependencias fundamentales:
sudo apt install texinfo libgccjit0 libgccjit-11-dev \
libjansson4 libjansson-dev gnutls-bin


# Dependencias para tree-sitter
sudo apt install libtree-sitter-dev

# Descargamos los fuentes, en este caso solo de la rama emacs-29
cd ~/tmp
git clone --single-branch --branch=emacs-29 http://git.savannah.gnu.org/r/emacs.git emacs29


# Preparamos el fichero configure
cd emacs29
export CC=/usr/bin/gcc-11 && export CXX=/usr/bin/gcc-11
./autogen.sh
./configure --without-compress-install \
            --with-tree-sitter \
            --with-native-compilation=aot \
            --with-xwidgets \
            --with-imagemagick \
            --prefix=/opt/emacs-29

# Opciones para investigar en el futuro:

#    --with-mailutils     # rely on GNU Mailutils, so that the --without-pop
                          # through --with-mailhost options are irrelevant; this
                          # is the default if GNU Mailutils is installed
                          # apt install mailutils

#    --with-xwidgets ( apt install libwebkit2gtk-4.1-dev)
#    --with-imagemagick

#    --with-json                  # included in emacs 27
#    --without-xft
#    --without-gif
#    --without-png
#    --without-jpg
#    --without-tiff
#    --without-sqlite3            # included in emacs
#    --without-compress-install   # dont compress some files when installing
#    --with-x-toolkit=[yes | no | gtk | gtk2 | gtk3 | lucid  | athena | motif] # gtk2 for Mate, gtk3 for Cinnamon
#    --with-imagemagick        # compile with imagemagick image support
#    --with-tree-sitter        # compile with tree-sitter support
#    --with-

./configure --without-compress-install \
            --with-tree-sitter \
            --with-native-compilation=aot \
            --with-xwidgets \
            --with-xtoolkit=gtk2 \
            --with-imagemagick \
            --prefix=/opt/emacs-30



# Compilamos con los nucleos que queramos (yo le dedico cuatro)
# Si no tienes prisa, con la opción bootstrap haces un 'clean' y
# recompilas todos los ficheros, incluidos los ficheros elisp

# make -j4
make -j4 bootstrap

# Comprobamos con
src/emacs -q

# Instalamos
make check
sudo make install

Podemos hacer git tag --list para ver todas las versiones disponibles, y con git checkout nos cambiamos a la versión que nos interese para compilarla.

Tanto si hemos clonado una rama específica como todo el repo para actualizar las fuentes basta con git pull

0%