Anatomía de un SlackBuild

12 de diciembre de 2025 • fjbalon

Como usuario de Slackware, he usado alguna vez scripts de SlackBuild para crear un paquete de software que pueda ser instalado fácil y limpiamente, y eliminado más tarde si es necesario con la misma facilidad y limpieza. Lo veremos en más profundidad más adelante, pero resumidamente sabemos que un SlackBuild es un script de shell que nos permite compilar e instalar paquetes desde el código fuente, creando un paquete -generalmente txz, aunque también tgz- y se instala mediante la herramienta nativa de Slackware installpkg. Se distribuyen principalmente en el repositorio oficial de slackbuilds.org.

Al final, los SlackBuilds constituyen la forma oficial, digamos, de instalar software que mno viene en los repositorios base de Slackware.

Existen diferentes enfoques de un script de SlackBuild, por ejemplo Alien Bob tiene su muy útil creador de SlackBuilds y, en términos generales, lo respetaremos. Y como ejemplo mediante el cual encarnar lo que vamos a describir, usaré el paquete ksh-openbsd. La descarga, generalmente, viene en un paquete comprimido .tar.gz, que se destarea y descomprime con tar xzvf, siendo el contenido del directorio:

ls
doinst.sh  ksh-openbsd.info  ksh-openbsd.SlackBuild  README  slack-desc

Siendo el que nos interesa realmente el script ksh-openbsd.SlackBuild (téngase en cuenta que he eliminado comentarios para una mejor legibilidad):

#!/bin/bash

cd $(dirname $0) ; CWD=$(pwd)

PRGNAM=ksh-openbsd
VERSION=${VERSION:-20190804}
BUILD=${BUILD:-1}
TAG=${TAG:-_SBo}
PKGTYPE=${PKGTYPE:-tgz}

if [ -z "$ARCH" ]; then
  case "$( uname -m )" in
    i?86) ARCH=i586 ;;
    arm*) ARCH=arm ;;
       *) ARCH=$( uname -m ) ;;
  esac
fi

if [ ! -z "${PRINT_PACKAGE_NAME}" ]; then
  echo "$PRGNAM-$VERSION-$ARCH-$BUILD$TAG.$PKGTYPE"
  exit 0
fi

TMP=${TMP:-/tmp/SBo}
PKG=$TMP/package-$PRGNAM
OUTPUT=${OUTPUT:-/tmp}

if [ "${ARCH}" == "i586" ];then
  SLKCFLAGS='-march=i586 -mtune=i686'
  LIBDIRSUFFIX=""
elif [ "$ARCH" == "i686" ]; then
  SLKCFLAGS="-march=i686 -mtune=i686"
  LIBDIRSUFFIX=""
elif [ "${ARCH}" == "x86_64" ];then
  SLKCFLAGS='-fPIC'
  LIBDIRSUFFIX="64"
else
  SLKCFLAGS="-O2"
  LIBDIRSUFFIX=""
fi

set -e

rm -Rf $PKG
mkdir -p $TMP $PKG $OUTPUT
cd $TMP
rm -Rf $PRGNAM-$VERSION
tar xvf $CWD/$PRGNAM-$VERSION.tar.gz
cd $PRGNAM-$VERSION
chown -R root:root .
find -L . \
 \( -perm 777 -o -perm 775 -o -perm 750 -o -perm 711 -o -perm 555 -o -perm 511 \) \
 -exec chmod 755 {} \+ -o \
 \( -perm 666 -o -perm 664 -o -perm 600 -o -perm 444 -o -perm 440 -o -perm 400 \) \
 -exec chmod 644 {} \+

CFLAGS="$SLKCFLAGS $(getconf LFS_CFLAGS)" make

case "$(ps -o stat= -p $$)" in
  *+*) make check ;;   # running in foreground
  *)   echo '*** Not running "make check" because we are in the background.' ;;
esac

make install DESTDIR=$PKG

if [ -n "${PDKSH_BINNAME}" ];then
  mv $PKG/bin/pdksh $PKG/bin/"${PDKSH_BINNAME}"
  mv $PKG/usr/man/man1/pdksh.1 $PKG/usr/man/man1/"${PDKSH_BINNAME}".1
  mv $PKG/usr/man/man1/pdksh-sh.1 $PKG/usr/man/man1/"${PDKSH_BINNAME}"-sh.1
fi
BINNAME=${PDKSH_BINNAME:-pdksh}

strip --strip-unneeded $PKG/bin/"${BINNAME}"
gzip -9 $PKG/usr/man/man1/"${BINNAME}".1
gzip -9 $PKG/usr/man/man1/"${BINNAME}"-sh.1

mkdir -p $PKG/usr/doc/$PRGNAM-$VERSION
cp -a \
  Changelog.ksh-openbsd LEGAL README \
  $PKG/usr/doc/$PRGNAM-$VERSION
cp $CWD/README $PKG/usr/doc/$PRGNAM-$VERSION/README.ksh-openbsd
cat $CWD/$PRGNAM.SlackBuild > $PKG/usr/doc/$PRGNAM-$VERSION/$PRGNAM.SlackBuild

mkdir -p $PKG/install

Tras el shebang definimos las variables principales del paquete, como son PRGNAM (nombre del paquete, o sea, ksh-openbsd), VERSION (versión del software), BUILD (número de build del paquete Slackware, por defecto 1), TAG (etiqueta que se añade al paquete, como _SBo = SlackBuilds.org) y PKGTYPE (tipo de paquete, tgz en este caso).

if [ -z "$ARCH" ]; then
  case "$( uname -m )" in
    i?86) ARCH=i586 ;;
    arm*) ARCH=arm ;;
       *) ARCH=$( uname -m ) ;;
  esac
fi

Detectamos automáticamente la arquitectura del equipo si el usuario no la tiene definida.

if [ ! -z "${PRINT_PACKAGE_NAME}" ]; then
  echo "$PRGNAM-$VERSION-$ARCH-$BUILD$TAG.$PKGTYPE"
  exit 0
fi

Es una parte muy útil para herramientas de gestión de paquetes como sbopkg o sbotools. Si la variable PRINT_PACKAGE_NAME está definida, aunque vacía, el script imprimirá el nombre completo del paquete (ksh-openbsd-20190804-x86_64-1_SBo.tgz). Esto permite a los gestores de paquetes saber el nombre sin tener que construir todo.

Después definirá los entornos de trabajo en TMP (por defecto /tmp/SBo), PKG (directorio donde se va a instalar el software en la fase de compilación) y OUTPUT (dónde se almacenará el .tgz final).

if [ "${ARCH}" == "i586" ];then
  SLKCFLAGS='-march=i586 -mtune=i686'
  LIBDIRSUFFIX=""
elif [ "$ARCH" == "i686" ]; then
  SLKCFLAGS="-march=i686 -mtune=i686"
  LIBDIRSUFFIX=""
elif [ "${ARCH}" == "x86_64" ];then
  SLKCFLAGS='-fPIC'
  LIBDIRSUFFIX="64"
else
  SLKCFLAGS="-O2"
  LIBDIRSUFFIX=""
fi

En este punto definimos las variables SLKCFLAGS y LIBDIRSUFFIX, utilizadas para optimización en función de la arquitectura previamente reconocida; y para la toma de decisión del uso del directorio /usr/lib o /usr/lib64, en función -de nuevo- de la arquitectura.

A partir de aquí podemos decir que la técnica se inicia, una vez realizadas las parametrizaciones técnicas iniciales. La línea que contiene set -e indica al intérprete que si cualquier comando devuelve un error (código de salida distinto de 0), el script se detiene inmediatamente. Es una medida de seguridad muy común en este tipo de scripts.

rm -Rf $PKG
mkdir -p $TMP $PKG $OUTPUT
cd $TMP
rm -Rf $PRGNAM-$VERSION
tar xvf $CWD/$PRGNAM-$VERSION.tar.gz
cd $PRGNAM-$VERSION
chown -R root:root .
find -L . \
 \( -perm 777 -o -perm 775 -o -perm 750 -o -perm 711 -o -perm 555 -o -perm 511 \) \
 -exec chmod 755 {} \+ -o \
 \( -perm 666 -o -perm 664 -o -perm 600 -o -perm 444 -o -perm 440 -o -perm 400 \) \
 -exec chmod 644 {} \+

Entonces elimina el directorio $PKG, por si hubiera una compilación anterior fallida o lo que fuera. Después, crea -si no existen- los directorios de trabajo previamente definidos. Nos movemos a /tmp/SBo, borra cualquier directorio que pudiera haber de código fuente, extrae con tar xvf el tarball que debe estar en la misma carpeta que el SlackBuild ($CWD) y accedemos a la carpeta del código fuente.

Entonces, aplicamos una "reparación de permisos", que inicia cambiando el propietario recursivamente a root:root y, mediante el comando find, buscamos archivos y carpetas con permisos inusuales, o demasiado permisivos. Los ejecutables o directorios se pondrán en permiso 755 (rwxr-xr-x), el resto de archivos en 644 (rw-r--r--).

Después, con CFLAGS="$SLKCFLAGS $(getconf LFS_CFLAGS)" make definimos variables de entorno para el comando make, utilizando los parámetros del inicio y ejecutando getconf para obtener otros parámetros necesarios.

case "$(ps -o stat= -p $$)" in
  *+*) make check ;;   # running in foreground
  *)   echo '*** Not running "make check" because we are in the background.' ;;
esac

Es entonces cuando iniciamos la fase de compilación. En términos generales se realiza directament el make, pero se ve que el programador de este paquete de ejemplo le añadió algo de complejidad: a veces, parece qu eel paquete en instalación (ksh-openbsd, recuerdo) se cuelga durante el make check, que indica una fase de testing, cuando se ejecuta en segundo plano. Esto ocurre con más frecuencia cuando se usa sbopkg, queue o scripts de compilación masiva. El test se quedaría esperando algo de terminal/entrada y bloquea toda la cola. ¿La solución? sencilla: si estoy ejecutando el SlackBuild manualmente en una términal, haga los test; si no, ignórelos.

Entonces, sí hacemos el make con make install DESTDIR=$PKG sobre el directorio de trabajo final.

if [ -n "${PDKSH_BINNAME}" ];then
  mv $PKG/bin/pdksh $PKG/bin/"${PDKSH_BINNAME}"
  mv $PKG/usr/man/man1/pdksh.1 $PKG/usr/man/man1/"${PDKSH_BINNAME}".1
  mv $PKG/usr/man/man1/pdksh-sh.1 $PKG/usr/man/man1/"${PDKSH_BINNAME}"-sh.1
fi
BINNAME=${PDKSH_BINNAME:-pdksh}

Si el usuario define la variable de entorno PDKSH_BINNAME antes de ejecutar el script, entonces renombra todo para que el shell no se llame pdksh. Por ejemplo, si el usuario ha ejecutado antes PDKSH_BINNAME=ksh ./ksh-openbsd.SlackBuild, el binario pasaría a llamarse ksh en lugar de pdksh (renombrando a su vez las páginas de manual correspondientes, claro está).

strip --strip-unneeded $PKG/bin/"${BINNAME}"
gzip -9 $PKG/usr/man/man1/"${BINNAME}".1
gzip -9 $PKG/usr/man/man1/"${BINNAME}"-sh.1

El comando strip sobre el binario principal elimina todos los símbolos de depuración y sesiones innecesarias del ejecutable, pero sin romper las funciones necesarias (de ahí que se use --strip-unneeded en lugar de --strip-all). Esto reduce considerablemente el tamaño del binario final. Es una práctica estándar en todos los paquetes de Slackware.

Después, comprime las páginas de manual con gzip usando el nivel máximo de compresión (-9).

mkdir -p $PKG/usr/doc/$PRGNAM-$VERSION
cp -a \
  Changelog.ksh-openbsd LEGAL README \
  $PKG/usr/doc/$PRGNAM-$VERSION
cp $CWD/README $PKG/usr/doc/$PRGNAM-$VERSION/README.ksh-openbsd
cat $CWD/$PRGNAM.SlackBuild > $PKG/usr/doc/$PRGNAM-$VERSION/$PRGNAM.SlackBuild

mkdir -p $PKG/install

Y finalmente, creamos el directorio con la documentación, copiamos ésta y, encima, copiamos el propio SlackBuild dentro de dicha carpeta. Esto está encarecidamente recomendado por las buenas prácticas de un SlackBuild, puesto que permite al usuario final ver cómo se compiló el paquete en cualquier momento. Es útil además para depuraciónh y para reproducción, en caso necesario.

Además, crea el directorio /install dentro del propio paquete. Aquí almacenará los archivos de metadatos del paquete, como slack-desc, doinst.sh, slack-required, slack-conflicts, etcétera.

Como hemos visto, el contenido de un SlackBuild es muy completo, contando con todas las fases de despliegue de un software: preparación, parametrización, configuración de compilación o pre-compilación, extracción y limpieza, compilación, instalación, optimización, documentación, empaquetado final... Se trata de un guión y hoja de ruta poderosa para el usuario de Slackware, desde luego, y muy útil y práctica en el día a día de la administración de este sistema.