Post-Image

Creando paquetes RPM con specfile

Uno de los métodos para generar paquetería para distribuciones basadas en RPM es mediante Specfile.

Un archivo SPEC es un fichero de instrucciones que le dice a la herramienta rpmbuild como crear un RPM. Las indicaciones definidas en este fichero se envían al sistema de compilación en una seria de secciones. En la cabecera del fichero contiene una serie de metadatos que son los que se van a utilizar posteriormente en el cuerpo del fichero, esta es la sección encargada de las instrucciones.

En el preámbulo van datos como el nombre, versión, release estos tres datos serán los que conformen el nombre del fichero RPM que se va a crear. Estos datos los vemos por ejemplo cuando ejecutamos un rpm -qa.

Un ejemplo muy sencillo que he estado utilizando en mis últimas colaboraciones para el Pinephone es la creación de un paquete al que he llamado pinephone-helpers y que tiene como objectivo realizar las modificaciones necesarias y exclusivas de este dispositivo.

Name:           pinephone-helpers
Version:        v0.1.0
Release:        1%{?dist}
Summary:        Pinephone call audio routing

License:        GPLv3+
URL:            https://gitlab.com/slem.os/%{name}
Source1:        pinephone-boot.service
Source2:        pp-start.sh
Source3:        pp-stop.sh
Source5:        20-pinephone.conf
Source6:        eg25_audio_routing.sh
Source7:        pinephone-modem-audio.service
Source8:        pinephone-suspend-hook.sh
Source9:        HiFi.conf
Source10:       VoiceCall.conf
Source11:       PinePhone.conf
Source12:       opensuse-background.jpg
Source13:       square-hicolor.svg
Source15:       90_pinephone.gschema.override
Source16:       90-modem-manager.rules
Source17:       91-network-manager.rules
Source18:       opensuse.json
Source19:       opensuse-profile.sh
Source20:       10-proximity.rules
Source21:       20-pinephone-led.rules
Source22:       phosh-renice.service
Source23:       phosh_renice.sh
Source24:       99-automount-sd.rules
Source25:       90-usb-gadget-managed.rules
Source26:       90-modem-eg25.rules
Source27:       repomd.xml.key
Source28:       machine-info

BuildArch:      aarch64


BuildRequires:  systemd

%description
Turn on and off the modem automatically at boot, and listen for
new calls to automatically configure audio routing when detected.

%global debug_package %{nil}


%build


%install
mkdir -p $RPM_BUILD_ROOT/usr/bin
chmod +x %{SOURCE2}
cp %{SOURCE2} $RPM_BUILD_ROOT/usr/bin
chmod +x %{SOURCE3}
cp %{SOURCE3} $RPM_BUILD_ROOT/usr/bin
chmod +x %{SOURCE6}
cp %{SOURCE6} $RPM_BUILD_ROOT/usr/bin
mkdir -p $RPM_BUILD_ROOT/etc/systemd/system
cp %{SOURCE1} $RPM_BUILD_ROOT/etc/systemd/system
cp %{SOURCE7} $RPM_BUILD_ROOT/etc/systemd/system
mkdir -p $RPM_BUILD_ROOT/etc/NetworkManager/conf.d
cp %{SOURCE5} $RPM_BUILD_ROOT/etc/NetworkManager/conf.d
mkdir -p $RPM_BUILD_ROOT/usr/lib/systemd/system-sleep/
chmod +x %{SOURCE8}
cp %{SOURCE8} $RPM_BUILD_ROOT/usr/lib/systemd/system-sleep/
mkdir -p $RPM_BUILD_ROOT/usr/share/alsa/ucm2/PinePhone/
cp %{SOURCE9} $RPM_BUILD_ROOT/%{_datadir}/alsa/ucm2/PinePhone/
cp %{SOURCE10} $RPM_BUILD_ROOT/%{_datadir}/alsa/ucm2/PinePhone/
cp %{SOURCE11} $RPM_BUILD_ROOT/%{_datadir}/alsa/ucm2/PinePhone/
mkdir -p $RPM_BUILD_ROOT/%{_datadir}/wallpapers
cp %{SOURCE12} $RPM_BUILD_ROOT/%{_datadir}/wallpapers/
mkdir -p $RPM_BUILD_ROOT/%{_datadir}/icons/vendor/scalable/emblems/
cp %{SOURCE13} $RPM_BUILD_ROOT/%{_datadir}/icons/vendor/scalable/emblems/emblem-vendor.svg
mkdir -p $RPM_BUILD_ROOT/%{_datadir}/glib-2.0/schemas/
cp %{SOURCE15} $RPM_BUILD_ROOT/%{_datadir}/glib-2.0/schemas/90_pinephone.gschema.override
mkdir -p $RPM_BUILD_ROOT/%{_datadir}/polkit-1/rules.d/
cp %{SOURCE16} $RPM_BUILD_ROOT/%{_datadir}/polkit-1/rules.d/
cp %{SOURCE17} $RPM_BUILD_ROOT/%{_datadir}/polkit-1/rules.d/
mkdir -p $RPM_BUILD_ROOT/%{_datadir}/feedbackd/themes
cp %{SOURCE18} $RPM_BUILD_ROOT/%{_datadir}/feedbackd/themes/
mkdir -p $RPM_BUILD_ROOT/etc/profile.d/
cp %{SOURCE19} $RPM_BUILD_ROOT/etc/profile.d/
mkdir -p $RPM_BUILD_ROOT/etc/udev/rules.d
cp %{SOURCE20} $RPM_BUILD_ROOT/etc/udev/rules.d/
cp %{SOURCE21} $RPM_BUILD_ROOT/etc/udev/rules.d/
cp %{SOURCE22} $RPM_BUILD_ROOT/etc/systemd/system/
chmod +x %{SOURCE23}
cp %{SOURCE23} $RPM_BUILD_ROOT/usr/bin/phosh_renice
cp %{SOURCE24} $RPM_BUILD_ROOT/etc/udev/rules.d/
cp %{SOURCE25} $RPM_BUILD_ROOT/etc/udev/rules.d/
cp %{SOURCE26} $RPM_BUILD_ROOT/etc/udev/rules.d/
mkdir -p $RPM_BUILD_ROOT/opt/
cp %{SOURCE27} $RPM_BUILD_ROOT/opt/
mkdir -p $RPM_BUILD_ROOT/etc/profile.d
cp %{SOURCE28} $RPM_BUILD_ROOT/etc/

%post
%systemd_post pinephone-boot.service
%systemd_post pinephone-modem-audio.service
%systemd_post phosh-renice.service
systemctl enable pinephone-boot.service
systemctl enable pinephone-modem-audio.service
systemctl enable phosh-renice.service


%preun
%systemd_preun pinephone-boot.service
%systemd_preun pinephone-modem-audio.service
%systemd_preun phosh-renice.service

%postun
%systemd_postun_with_restart pinephone-boot.service
%systemd_postun_with_restart pinephone-modem-audio.service
%systemd_postun_with_restart phosh-renice.service

%files
%{_bindir}/*
%{_sysconfdir}/systemd/system/*
%dir %{_sysconfdir}/NetworkManager
%dir %{_sysconfdir}/NetworkManager/conf.d
%{_sysconfdir}/NetworkManager/conf.d/20-pinephone.conf
/usr/lib/systemd/system-sleep/pinephone-suspend-hook.sh
%dir %{_datadir}/alsa
%dir %{_datadir}/alsa/*
%{_datadir}/alsa/ucm2/PinePhone/
%dir %{_datadir}/wallpapers
%{_datadir}/wallpapers/*
%dir %{_datadir}/icons
%dir %{_datadir}/icons/vendor
%dir %{_datadir}/icons/vendor/scalable
%dir %{_datadir}/icons/vendor/scalable/emblems
%{_datadir}/icons/vendor/scalable/emblems/emblem-vendor.svg
%dir %{_datadir}/glib-2.0
%dir %{_datadir}/glib-2.0/schemas/
%{_datadir}/glib-2.0/schemas/90_pinephone.gschema.override
%dir %{_datadir}/polkit-1
%dir %{_datadir}/polkit-1/rules.d/
%{_datadir}/polkit-1/rules.d/*
%dir %{_datadir}/feedbackd/
%dir %{_datadir}/feedbackd/themes/
%{_datadir}/feedbackd/themes/opensuse.json
%dir /etc/
/etc/*
%dir /etc/udev/
%dir /etc/udev/rules.d/
/etc/udev/rules.d/*
%dir /opt/
/opt/repomd.xml.key
%dir /etc/profile.d
/etc/profile.d/*

%changelog

Aquí vemos los diferentes apartados, en primer lugar definimos el nombre y los ficheros que vamos a utilizar para crear el paquete RPM así como una breve descripción, luego comienza el proceso de construcción e instalación y para finalizar se indican los ficheros que han sido instalados y el destino que deben tener en la máquina una vez instalado el paquete.

Algunos errores comunes que me he encontrado en mis comienzos en la creación de paquetería RPM han sido:

  • Errores por falta de dependencias a la hora de compilar un nuevo paquete, también mencionar que en algunas ocasiones me he encontrado con la problemática de que en cada distribución los paquetes que contienen ciertas librerías son diferentes, principalmente estas diferencias provienen entre distribuciones basadas en paquetería DEV y RPM.

  • Fallos en la parte de los ficheros y las rutas en las que debe ir una vez el paquete este instalado, principalmente me he encontrado con problemas de permisos sobre ciertas carpetas, ya que para poder desplegar un fichero en una ruta el propietario de la carpeta debe ser el propio paquete, o lo que es lo mismo, el paquete debe tener permisos para dejar el fichero en la ruta especificada en el %files.

  • Ficheros descomprimidos pero no añadidos para su instalación, me he encontrado muchas veces con ficheros debug que son resultado de la compilación o bien ficheros que se compilan pero que no tienen que ser añadidos en el paquete final. La solución a esto se puede hacer con %global debug_package %{nil} o bien con la partícula exclude.

Links de interés:
openSUSE wiki, specfile guidelines
RPM.org, creating specfile
RPM packaginf guide
Fedora wiki, how to create an RPM