Casi todo el software que necesitas en un servidor está disponible como paquete en los repositorios de tu distribución, y esa debería ser siempre la primera opción: recibe actualizaciones de seguridad con apt upgrade sin que tengas que hacer nada. Aun así, a veces necesitas una versión más nueva que la del repositorio, activar una opción que solo se elige al compilar o aplicar un parche propio. En este tutorial compilarás un programa real (GNU Hello) con el flujo clásico configure, make y make install en Ubuntu 24.04, verificarás la firma del código fuente, lo instalarás en /usr/local sin interferir con los paquetes del sistema y aprenderás a desinstalarlo. Al final verás cómo se aplica lo mismo a proyectos que usan CMake o Meson.

Requisitos previos

  • Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath. En Debian 12 los comandos son los mismos.
  • Un usuario no root con privilegios sudo.
  • Unos cientos de MB libres en disco. Proyectos grandes (un kernel, un navegador, LLVM) pueden necesitar varios GB y bastante RAM.

Cuándo compilar y cuándo no

Antes de empezar, conviene tener claro qué ganas y qué pierdes:

Paquete de la distribuciónCompilado desde código fuente
Actualizaciones de seguridadAutomáticas con apt upgradeManuales: tienes que recompilar
VersiónLa que congela la distribuciónLa que elijas
Opciones de compilaciónLas que decidió el mantenedorLas que tú actives o desactives
Desinstalaciónapt removeDepende de que guardes el directorio de compilación

Compila solo cuando el paquete no exista, se haya quedado corto o necesites una opción concreta. Si el proyecto ofrece un repositorio oficial de paquetes para Ubuntu (Nginx, PostgreSQL, Docker, Node.js...), suele ser mejor opción que compilar.

Paso 1: Instalar las herramientas de compilación

El metapaquete build-essential instala el compilador de C y C++ (gcc, g++), make, las cabeceras de la biblioteca estándar y dpkg-dev. Añade también pkg-config, que muchos scripts configure usan para localizar bibliotecas, y wget para descargar el código:

sudo apt update
sudo apt install build-essential pkg-config wget

Comprueba que el compilador y make responden:

gcc --version
make --version
gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0
...
GNU Make 4.3
...

Los números exactos pueden variar según las actualizaciones de Ubuntu.

Paso 2: Descargar y verificar el código fuente

Trabaja en un directorio de tu usuario, nunca como root. Crea uno para tus compilaciones y entra en él:

mkdir -p ~/src
cd ~/src

Descarga el archivo de GNU Hello y su firma desde el servidor oficial de GNU:

wget https://ftp.gnu.org/gnu/hello/hello-2.12.1.tar.gz
wget https://ftp.gnu.org/gnu/hello/hello-2.12.1.tar.gz.sig

Verificar la firma garantiza que el archivo no se ha modificado desde que lo publicó el mantenedor. GNU publica un anillo con las claves de todos sus mantenedores; descárgalo y úsalo para comprobar la firma:

wget https://ftp.gnu.org/gnu/gnu-keyring.gpg
gpg --keyring ./gnu-keyring.gpg --verify hello-2.12.1.tar.gz.sig hello-2.12.1.tar.gz

La línea que importa es la de firma correcta:

gpg: Good signature from "..."

GnuPG mostrará además un aviso de que la clave no está certificada con una firma de confianza. Es normal: significa que no has marcado la clave como de confianza en tu propio anillo, no que la firma sea mala. Si ves BAD signature, borra el archivo y no lo uses.

Descomprime el archivo y entra en el directorio:

tar -xzf hello-2.12.1.tar.gz
cd hello-2.12.1

Lee siempre los archivos README e INSTALL del proyecto. Ahí se indican las dependencias y las opciones de compilación específicas:

ls
ABOUT-NLS  ChangeLog  INSTALL  Makefile.in  README  configure  ...

Paso 3: Configurar la compilación

El script configure (generado con GNU Autotools) comprueba tu sistema, detecta el compilador y las bibliotecas disponibles y genera los Makefile adaptados a tu máquina. Para ver todas las opciones que admite el proyecto:

./configure --help | less

La opción más importante es --prefix, que decide dónde se instalará todo. El valor por defecto es /usr/local, que está reservado precisamente para software instalado a mano: los paquetes de Ubuntu van a /usr y nunca tocan /usr/local, así que no habrá conflictos. Indícalo de forma explícita para que quede claro:

./configure --prefix=/usr/local

Al final verás que se crean los archivos de compilación:

...
config.status: creating Makefile
config.status: creating po/Makefile.in
config.status: creating config.h
config.status: executing depfiles commands
config.status: executing po-directories commands

Si configure termina con un error del tipo configure: error: ... not found, falta una dependencia. Consulta la sección de solución de problemas más abajo; el detalle completo de cada comprobación queda en el archivo config.log.

Otras opciones habituales en proyectos con Autotools:

  • --enable-FEATURE / --disable-FEATURE: activa o desactiva funciones opcionales.
  • --with-PAQUETE / --without-PAQUETE: usa o ignora una biblioteca externa.
  • CFLAGS="-O2": pasa opciones al compilador. Los valores por defecto (-g -O2) ya son adecuados para producción; evita -march=native si vas a copiar el binario a otra máquina con otro procesador.

Paso 4: Compilar

Lanza la compilación usando todos los núcleos disponibles con -j. nproc devuelve el número de CPU:

make -j"$(nproc)"

Si termina sin ninguna línea que empiece por error:, el binario está listo en el propio directorio. Muchos proyectos incluyen una batería de pruebas; ejecútala antes de instalar:

make check
...
============================================================================
Testsuite summary for GNU Hello 2.12.1
============================================================================
# TOTAL: 7
# PASS:  7
# SKIP:  0
# XFAIL: 0
# FAIL:  0
# XPASS: 0
# ERROR: 0
============================================================================

El número de pruebas puede cambiar entre versiones. Lo importante es que FAIL y ERROR estén a 0.

Paso 5: Instalar en /usr/local

Solo este paso necesita sudo, porque copia archivos a directorios del sistema:

sudo make install

Comprueba que el binario queda en la ruta esperada y que el shell lo encuentra antes que cualquier otra versión (/usr/local/bin va antes que /usr/bin en el PATH de Ubuntu):

command -v hello
hello --version
hello
/usr/local/bin/hello
hello (GNU Hello) 2.12.1
...
Hello, world!

Si el programa instala bibliotecas compartidas en /usr/local/lib, actualiza la caché del enlazador dinámico para que los ejecutables las encuentren. En Ubuntu /usr/local/lib ya está incluido en /etc/ld.so.conf.d/libc.conf, solo hay que refrescar la caché:

sudo ldconfig

Ver qué archivos se instalan antes de instalarlos

make install no deja un registro de los archivos que copia. Si quieres revisarlo antes, haz una instalación de prueba en un directorio temporal con DESTDIR, que antepone esa ruta a todos los destinos:

make install DESTDIR="$HOME/stage-hello"
find "$HOME/stage-hello" -type f
/home/your_user/stage-hello/usr/local/bin/hello
/home/your_user/stage-hello/usr/local/share/man/man1/hello.1
/home/your_user/stage-hello/usr/local/share/info/hello.info
...

Guarda esa lista si quieres borrar los archivos a mano en el futuro, y elimina el directorio de prueba cuando termines con rm -rf "$HOME/stage-hello".

Paso 6: Desinstalar o actualizar

Los proyectos basados en Automake generan un objetivo uninstall. Para usarlo necesitas el directorio de compilación configurado con las mismas opciones, así que no lo borres después de instalar:

cd ~/src/hello-2.12.1
sudo make uninstall

Comprueba que el binario ya no está:

command -v hello || echo "hello no está instalado"

Para actualizar a una versión nueva, repite los pasos 2 a 5 con el nuevo archivo. Antes de instalar la versión nueva, ejecuta sudo make uninstall en el directorio de la antigua para no dejar archivos huérfanos de la versión anterior.

Instalar las dependencias de compilación

GNU Hello no tiene dependencias externas, pero la mayoría de programas sí. En Ubuntu cada biblioteca tiene un paquete de ejecución (por ejemplo libssl3t64) y otro de desarrollo con las cabeceras, terminado en -dev (libssl-dev). Para compilar necesitas los paquetes -dev.

Si el programa que quieres compilar también existe en los repositorios de Ubuntu, aunque sea en una versión antigua, puedes instalar de golpe todas las dependencias de compilación que usa el paquete. Primero activa los repositorios de código fuente editando el archivo de fuentes:

sudo nano /etc/apt/sources.list.d/ubuntu.sources

En cada bloque cambia la línea Types: deb por:

Types: deb deb-src

Actualiza el índice e instala las dependencias. Este ejemplo usa nginx:

sudo apt update
sudo apt build-dep nginx

La versión nueva puede necesitar alguna biblioteca adicional que no usaba el paquete antiguo, pero así partes de una base casi completa.

Otros sistemas de compilación: CMake y Meson

Cada vez más proyectos sustituyen Autotools por CMake o Meson. Las ideas son las mismas (configurar, compilar, instalar), cambian los comandos. Identifica el sistema por los archivos del directorio raíz: configure (Autotools), CMakeLists.txt (CMake) o meson.build (Meson).

CMake

Instala CMake:

sudo apt install cmake

Desde el directorio del proyecto, configura en un subdirectorio build separado del código, compila e instala:

cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/local
cmake --build build -j"$(nproc)"
sudo cmake --install build

CMake guarda la lista de archivos instalados en build/install_manifest.txt. Es la forma de saber qué borrar más adelante:

cat build/install_manifest.txt

Las opciones del proyecto se pasan con -DOPCION=valor en el paso de configuración. Para listarlas, ejecuta cmake -LH build después de configurar.

Meson

Meson usa Ninja como motor de compilación:

sudo apt install meson ninja-build

Configura, compila e instala:

meson setup build --prefix=/usr/local --buildtype=release
meson compile -C build
sudo meson install -C build

Para desinstalar, Meson ofrece un objetivo propio: sudo ninja -C build uninstall. Las opciones del proyecto se ven con meson configure build.

Solución de problemas

configure: error: ... not found o Package 'xxx' was not found

Falta una biblioteca o su paquete de desarrollo. Busca el paquete -dev correspondiente:

apt search libxxx | grep -- -dev

Si el error menciona un archivo concreto (por ejemplo zlib.h), apt-file te dice qué paquete lo contiene:

sudo apt install apt-file
sudo apt-file update
apt-file search zlib.h

Instala el paquete indicado y vuelve a ejecutar ./configure.

fatal error: xxx.h: No such file or directory durante make

Es el mismo problema detectado más tarde: una cabecera que configure no comprobó. Encuentra el paquete con apt-file search xxx.h, instálalo y repite make.

error while loading shared libraries: libxxx.so.N al ejecutar el programa

El binario no encuentra una biblioteca que instalaste en /usr/local/lib. Ejecuta sudo ldconfig. Si la instalaste en otro prefijo, añade la ruta en un archivo de /etc/ld.so.conf.d/ y vuelve a ejecutar sudo ldconfig.

El sistema sigue usando la versión antigua

Comprueba qué binario se ejecuta con command -v programa. Si has abierto la sesión antes de instalar, el shell puede tener la ruta antigua en caché; ejecuta hash -r o abre una nueva sesión.

El compilador muere sin mensaje claro o aparece Killed

El sistema se ha quedado sin memoria. Compila con menos trabajos en paralelo (make -j2 o make) o añade un archivo de intercambio.

Conclusión

Has compilado un programa con el flujo configure, make, make install, verificado la firma del código, instalado en /usr/local sin tocar los paquetes del sistema y aprendido a desinstalarlo, además de los equivalentes en CMake y Meson. Recuerda que el software compilado no se actualiza solo: suscríbete a los avisos de seguridad del proyecto y recompila cuando salga una versión nueva. Como siguientes pasos, puedes empaquetar tus compilaciones como .deb con dpkg-deb para distribuirlas entre servidores, o crear una unidad de systemd para ejecutar como servicio un demonio que hayas compilado.