Autotools básico

Propósito

Crear paquetes de código fuente utilizando las herramientas de construcción de GNU (Autoconf, Automake y Libtool) a partir de uno o más ficheros de código fuente y los ficheros configure.ac y Makefile.am.

Esta guía muestra cómo a partir de un fichero fuente holamundo.c y el par de ficheros mencionados anteriormente se generará un archivo llamado holamundo-1.0.0.tar.gz que una vez desempaquetado se pueda compilar e instalar con el típico “./configure && make && sudo make install“.

En una próxima entrada se explicará cómo trabajar con dependencias (librerías).

Ventajas

  • Portabilidad, permite generar makefiles compatibles con diferentes implementaciones de Make, múltiples compiladores e intérpretes y generar scripts compatibles con múltiples shell.
  • Multiplataforma, los scripts generados facilitan las comprobaciones y configuraciones necesarias para generar una compilación cruzada, por ejemplo generar binarios para otra arquitectura agregando pocos parámetros.

Herramientas

  • autoconf, se encarga de generar el script configure a partir del fichero configure.ac.
  • automake, genera el fichero Makefile.in a partir del fichero Makefile.am.
  • libtool, gestiona la creación de librerías estáticas y dinámicas, y también la carga (en tiempo de ejecución) de librerías dinámicas.

Dentro del paquete autoconf hay otras herramientas relevantes como aclocal y autoheader. En este ejemplo básico se ejecutan de forma automática todas las herramientas mencionadas utilizando la herramienta autoreconf.

Herramientas relacionadas

  • make, procesa archivos Makefile. Existen varias implementaciones (GNU Make, BSD Make…) con algunas incompatibilidades que autotools solventa.
  • pkg-config, facilita información sobre la mayoría de las librerías instaladas en el sistema (ubicación, dependencias, versión, etc.).

¡Hola, Autotools!

Para crear el ejemplo básico de paquete es conveniente disponer de una carpeta de trabajo para tenerlo mejor organizado.

  • Crear una carpeta holamundo con una subcarpeta src para el código fuente y a continuación ubicarse en la carpeta de trabajo:
mkdir -p holamundo/src
cd holamundo

src/holamundo.c

  • Crear un fichero de código fuente C en src/holamundo.c:
#include <stdio.h>

int main() {
    printf("Hola Mundo!\n");

    return 0;
}

Makefile.am

  • Crear un fichero Makefile.am:
bin_PROGRAMS = holamundo
holamundo_SOURCES = src/holamundo.c

configure.ac

  • Ejecutar la herramienta autoscan en la carpeta de trabajo. Creará un fichero llamado configure.scan que hay que renombrar a configure.ac:
autoscan
mv configure.scan configure.ac

Nos habrá generado un fichero configure.ac parecido al siguiente:

#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ([2.69])
AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS])
AC_CONFIG_SRCDIR([src/holamundo.c])
AC_CONFIG_HEADERS([config.h])

# Checks for programs.
AC_PROG_CC

# Checks for libraries.

# Checks for header files.

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.

AC_CONFIG_FILES([Makefile])
AC_OUTPUT
  • Modificar la macro AC_INIT del fichero configure.ac para mostrar el nombre del paquete, versión y dirección para avisar sobre errores (correo electrónico o web):
AC_INIT([holamundo], [1.0.0], [****@fran.cr])
  • Agregar la macro AM_INIT_AUTOMAKE en el fichero configure.ac para poder generar los Makefiles. Un buen lugar sería después de la línea de AC_CONFIG_HEADERS:
AM_INIT_AUTOMAKE([foreign subdir-objects])

Una vez modificado el fichero configure.ac debería ser parecido al siguiente:

#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ([2.69])
AC_INIT([holamundo], [1.0.0], [****@fran.cr])
AC_CONFIG_SRCDIR([src/holamundo.c])
AC_CONFIG_HEADERS([config.h])
AM_INIT_AUTOMAKE([foreign subdir-objects])

# Checks for programs.
AC_PROG_CC

# Checks for libraries.

# Checks for header files.

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.

AC_CONFIG_FILES([Makefile])
AC_OUTPUT

Generar configure y Makefile.in

  • Ejecutar:
autoreconf -i

Generar Makefile

./configure

Generar paquete (“tarball”)

make dist

Se habrá generado holamundo-1.0.0.tar.gz

Instalación genérica del paquete

  • Descomprimir:
tar xf holamundo-1.0.0.tar.gz
  • Entrar en la carpeta comprimida:
cd holamundo-1.0.0
  • Generar Makefile:
./configure
  • Construir:
make
  • Instalar:
sudo make install

Detalles de los ficheros creados

Makefile.am

bin_PROGRAMS indica la lista de programas (binarios en este caso) que va a crearse. En este caso se va a crear un binario llamado holamundo.

holamundo_SOURCES indica que nuestro holamundo tiene un listado de _SOURCES (ficheros fuente). En este ejemplo solamente hay uno (src/holamundo.c). Si el proyecto tuviera más ficheros de código fuente para crear el programa se separan con espacios. Si se desea poner un fichero por línea para hacer el mantenimiento de Makefile.am más limpio se puede utilizar \ al final de la línea para indicar que continúa en la siguiente, por lo tanto:

holamundo_SOURCES = \
    fichero1.c \
    fichero2.c \
    fichero3.c

es lo mismo que:

holamundo_SOURCES = fichero1.c fichero2.c fichero3.c

configure.ac

foreign indica que no se está creando un paquete GNU estándar (no exigirá la existencia de los ficheros ChangeLog, COPYING, NEWS y README para funcionar).

subdir-objects indica que se está usando el modo recursivo, es decir, no se van a usar múltiples ficheros Makefile.am para cada carpeta con objetivos a procesar.

AC_PREREQ indica la versión mínima de autoconf requerida para funcionar con el archivo de configuración.

AC_CONFIG_SRCDIR comprueba que el código fuente existe en la carpeta indicada mediante la comprobación de algún fichero fuente de la misma.

AC_CONFIG_HEADERS indica el nombre que tendrá el archivo de configuración de código fuente generado. Esto permite crear definiciones (por ejemplo, #define LOQUESEA 1) en el archivo indicado (por defecto, config.h) que podrá ser incluido en el código fuente. Estas definiciones podrían variar según lo que compruebe el script configure, resultando muy útil por ejemplo para verificar si el programa se ha compilado con o sin soporte de una característica en particular, por ejemplo para dependencias opcionales de librerías o comprobaciones de funcionalidad del compilador o de un sistema operativo en tiempo de compilación.

AC_PROG_CC comprueba la existencia de un compilador de C. Como autoscan ha detectado código fuente en C se ha agregado esta macro automáticamente.

AC_CONFIG_FILES recibe en el primer parámetro una lista de ficheros separados con espacios. (en este caso solo Makefile, que generará a partir de Makefile.in). Los ficheros con extensión .in se utilizan para sustituir los valores de las variables que contienen y generar el archivo de salida, normalmente con el mismo nombre sin el .in. Este proceso lo realiza la macro AC_OUTPUT.

Algunos parámetros del script configure

El parámetro --prefix permite indicar el directorio base de instalación, que por defecto suele ser /usr/local. Por ejemplo el programa holamundo se copiaría por defecto a la carpeta /usr/local/bin si no se cambia el --prefix. Las distribuciones suelen usar en sus paquetes --prefix=/usr. Si se quiere instalar un paquete y no se tienen permisos de superusuario se podría indicar una ruta dentro de la $HOME donde usualmente se suelen tener permisos de escritura.

./configure --help muestra información detallada de los parámetros.

Compilación cruzada con el script configure

El parámetro --host permite utilizar de forma sencilla toolchains para compilación cruzada, por ejemplo en una máquina Intel con Ubuntu e instalando el paquete gcc-arm-linux-gnueabihf proporciona el toolchain para ARMv7 (hard float) y puede realizarse esto:

./configure --host=arm-linux-gnueabihf
make

A continuación podemos verificar que el ejecutable holamundo es un ELF para arquitectura ARM y no para Intel mediante:

file holamundo

por lo que podremos comprobar que efectivamente se utilizaron las herramientas del toolchain sin tener que prefijar individualmente compilador, enlazador y demás ejecutables.

Cómo instalar Firma Digital de Costa Rica en GNU/Linux Ubuntu 16.04

Esta guía documenta cómo instalar el controlador de la tarjeta de Firma Digital de Costa Rica y la jerarquía de certificados del Banco Central (SINPE) y del MICITT en el sistema operativo Ubuntu 16.04 de arquitectura Intel de 64 bits (x86_64). Para otros sistemas operativos se documentará más adelante.

El motivo de esta nueva guía de instalación tenía los siguientes propósitos:

  • Configurar de la forma más sencilla y adecuada el sistema para que funcione con la mayor cantidad de programas.
  • Lograr que funcione para todos los usuarios del sistema, incluyendo los nuevos usuarios creados tras las instalación.
  • Superar la prueba de firma digital (con applet Java) en el sitio web de Soporte Firma Digital con el navegador Mozilla Firefox.

Instalación de las dependencias

  • Instalar el soporte CCID de PC/SC para que reconozca el lector de tarjetas y el plugin NPAPI IcedTea-Web para poder cargar el applet Java que permite firmar desde el navegador Firefox:
sudo apt -y install pcscd icedtea-plugin

Descarga del “instalador”

  • Descargar el “instalador” en el desplegable llamado “Usuarios Linux” en la página de descarga de instaladores del sitio web de Soporte Firma Digital de Costa Rica, introduciendo el número de serie de la tarjeta y el captcha.

Desempaquetado del “instalador”

  • Descomprimir el archivo zip descargado, en el momento de escribir esta documentación se llama sfd_ClientesLinux_Rev08.zip. Se creará una carpeta llamada Firma Digital. Se asume que se ha descomprimido dentro de la carpeta Descargas.

Instalación de los certificados

Es necesario agregar a la lista de confianza la jerarquía de certificados del SINPE y del MICITT. Para ello, un conjunto de comandos:

  • Copiar los certificados:
sudo cp Descargas/Firma\ Digital/Certificados/* /usr/local/share/ca-certificates/

sudo rename.ul .cer .crt /usr/local/share/ca-certificates/*.cer

for file in /usr/local/share/ca-certificates/*.crt; do sudo openssl x509 -inform DER -in "$file" -out "$file"; done 2>/dev/null
  • Regenerar los archivos de certificados para todas las aplicaciones:
sudo update-ca-certificates --fresh

Instalación del módulo PKCS#11

En Ubuntu todavía no existe una inciativa como la que existe en Fedora para solucionar el problema de unificación de NSS con Firefox, por lo que he considerado realizar un hack bastante intrusivo pero funcional para reemplazar las librerías NSS que resista a actualizaciones de Firefox, Thunderbird y NSS, siempre y cuando no haya cambios en la ubicación de las librerías, que es menos probable.

  • Copiar el módulo PKCS#11 propietario en /usr/lib/x86_64-linux-gnu/pkcs11/:
sudo cp Descargas/Firma\ Digital/Librería/x64/libASEP11.so /usr/lib/x86_64-linux-gnu/pkcs11/
  • Crear los siguientes enlaces simbólicos (necesarios para que funcionen algunos programas y applets):
sudo ln -s /usr/lib/x86_64-linux-gnu/pkcs11/libASEP11.so /usr/lib/x86_64-linux-gnu/

sudo ln -s /usr/lib/x86_64-linux-gnu/pkcs11/libASEP11.so /usr/lib/
  • Crear el fichero /etc/Athena/IDPClientDB.xml y abrirlo para edición:
sudo mkdir /etc/Athena/

sudo gedit /etc/Athena/IDPClientDB.xml
  • En la ventana del editor de textos gedit, pegar el siguiente texto, guardar y cerrar el editor:
<?xml version="1.0" encoding="utf-8" ?>
<IDProtect>
 <TokenLibs>
  <IDProtect>
   <Cards>
    <IDProtectXF>
     <ATR type='hexBinary'>3BDC00FF8091FE1FC38073C821106600000000000000</ATR>
     <ATRMask type='hexBinary'>FFFF00FFF0FFFFFFFFFFFFFFFFF0FF00000000000000</ATRMask>
    </IDProtectXF>
   </Cards>
  </IDProtect>
 </TokenLibs>
</IDProtect>
  • Crear un fichero llamado /etc/pkcs11/modules/firmadigital.module y abrirlo para edición:
sudo mkdir -p /etc/pkcs11/modules/

sudo gedit /etc/pkcs11/modules/firmadigital.module
  • En la ventana del editor de textos gedit, pegar el siguiente texto, guardar y cerrar el editor:
module: libASEP11.so
  • Crear un fichero llamado /usr/local/sbin/update-p11-kit-symlinks y abrirlo para edición:
sudo gedit /usr/local/sbin/update-p11-kit-symlinks
  • En la ventana del editor de textos gedit, pegar el siguiente texto, guardar y cerrar el editor:
#!/bin/sh

FIREFOX_LIB=/usr/lib/firefox/libnssckbi.so
THUNDERBIRD_LIB=/usr/lib/thunderbird/libnssckbi.so

if ! [ -L "$FIREFOX_LIB" ]
then
    echo "Firefox libnssckbi.so is not a symlink. Fixing..."
    mv -f "$FIREFOX_LIB" "$FIREFOX_LIB".bak
    ln -s /usr/lib/x86_64-linux-gnu/p11-kit-proxy.so "$FIREFOX_LIB"
fi

if ! [ -L "$THUNDERBIRD_LIB" ]
then
    echo "Thunderbird libnssckbi.so is not a symlink. Fixing..."
    mv -f "$THUNDERBIRD_LIB" "$THUNDERBIRD_LIB".bak
    ln -s /usr/lib/x86_64-linux-gnu/p11-kit-proxy.so "$THUNDERBIRD_LIB"
fi
  • Agregar el atributo de ejecutable al script:
sudo chmod +x /usr/local/sbin/update-p11-kit-symlinks
  • Crear un fichero llamado /etc/systemd/system/p11-kit-proxy-updater.service y abrirlo para edición:
sudo gedit /etc/systemd/system/p11-kit-proxy-updater.service 
  • En la ventana del editor de textos gedit, pegar el siguiente texto, guardar y cerrar el editor:
[Unit]
Description=mantenimiento de enlaces a p11-kit-proxy

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/update-p11-kit-symlinks

[Install]
WantedBy=multi-user.target

Activar el servicio al arranque y ejecutarlo una primera vez para comprobar que funciona:

sudo systemctl enable p11-kit-proxy-updater.service

sudo systemctl start p11-kit-proxy-updater.service

Eso es todo. Es necesario reiniciar Firefox, Thunderbird y cualquier otra aplicación que use certificados para que se apliquen los cambios. Si se ha insertado el lector y la tarjeta al lector, estas aplicaciones preguntarán por el PIN, lo que indicará que se la instalación ha sido exitosa.

En Firefox (hasta la versión 51 y la 52 ESR) ya se puede ir a realizar la prueba en el enlace “Verificación de Capacidad de Firma” del sitio web de Soporte Firma Digital de Costa Rica mencionado anteriormente y debería pasarla con éxito. En el navegador aparecerá que se quiere ejecutar “IcedTea-Web”, hay que permitirlo. Si el navegador hace preguntas sobre el applet responder afirmativamente y aceptar a todos los cuadros de mensaje que aparezcan e ingresar el PIN cuando lo solicite.