Si usa Red Hat Enterprise Linux (RHEL) o Fedora, pronto se encontrará usando dnf
(o yum
) para instalar paquetes de software. Red Hat Package Manager (RPM) es la herramienta de administración de software más importante en estas distribuciones de Linux. Este artículo muestra cómo puede aprovechar este marco para distribuir sus propias aplicaciones.
Con suerte, ha tenido la oportunidad de leer el artículo de Valentin Bajrami sobre el mismo tema. Repetiré algunos de los mismos conceptos aquí e ilustraré algunos problemas que puede encontrar en el camino. También usaré dos ejemplos más complejos e identificaré algunos problemas que puede encontrar al empaquetar aplicaciones nativas.
Este artículo le muestra cómo determinar cómo compilar y empaquetar su propia aplicación nativa para su distribución. En un artículo de seguimiento, explicaré cómo empaquetar aplicaciones de terceros que no tienen un paquete RPM o, si lo tienen, desea personalizarlo.
Los requisitos previos incluyen:
- Tiene conocimientos básicos sobre cómo usar RPM para consultar paquetes e instalar o eliminar paquetes. Si no, primero familiarícese con estos conceptos y luego regrese aquí para divertirse.
- Tiene instalados Make, Git, GCC y Java, ya que los necesitará para completar los ejercicios que se incluyen aquí. No es obligatorio, pero estaría bien que practicaras mientras avanzo.
Para instalar Make, GCC, Java 11 y Git con el administrador de paquetes DNF, ejecute:
$ sudo dnf install \
make gcc-10 java-11-openjdk-headless git
Empaque su propio software usando RPM
Este artículo usa un pequeño proyecto de código abierto llamado jdumpertools para este paso.
En su terminal Linux, clone jdumpertools
y luego compilarlo (has instalado Make y el compilador GCC, ¿verdad?):
$ git clone [email protected]:josevnz/jdumpertools.git
$ cd jdumpertools
$ make all
$ ls -l jdu jutmp *.so
-rwxrwxr-x 1 josevnz josevnz 32728 Oct 3 16:40 jdu
-rwxrwxr-x 1 josevnz josevnz 32752 Oct 3 16:40 jutmp
-rwxrwxr-x 1 josevnz josevnz 29024 Oct 3 16:40 libjdumpertools.so
Luego puede ejecutar cualquiera de los programas generados. Por ejemplo, pruebe jdu
(una versión más simple del du
comando que imprime los resultados en formato JSON):
$ LD_LIBRARY_PATH=$PWD $PWD/jdu /
[{"partition": "/", "free_space": 462140129280.000000, "total_space": 510405902336.000000}]
Hasta ahora todo bien.
El archivo jdumpertools.spec en este directorio es el archivo de especificación RPM que controla cómo compilar y empaquetar jdumpertools
utilizando RPM.
A continuación, instale algunas herramientas de apoyo antes de pasar a crear el archivo RPM.
Instalar bloques de construcción RPM
Obtenga las rpmdevtools
necesarias utilidades ejecutando:
$ sudo dnf install rpm-build rpmdevtools
A continuación, prepare el espacio aislado para crear RPM utilizando rpmdevtools
. Nunca use la raíz para este paso, sino su cuenta Linux personal o de desarrollador (pasará el -d
indicador de depuración):
$ rpmdev-setuptree -d
josevnz /home/josevnz /home/josevnz/.rpmmacros
/home/josevnz/rpmbuild/RPMS /home/josevnz/rpmbuild/SOURCES /home/josevnz/rpmbuild/SPECS
/home/josevnz/rpmbuild/SRPMS /home/josevnz/rpmbuild/BUILD
Aquí hay una mejor vista:
$ tree ~/rpmbuild
/home/josevnz/rpmbuild
├── BUILD
├── RPMS
├── SOURCES
├── SPECS
└── SRPMS
5 directories, 0 files
En este momento, debe prestar atención a solo dos directorios:SOURCES
y SPECS
. Explicaré los demás más tarde.
También hay un nuevo archivo llamado ~/.rpmmacros
. Puede colocar o anular algunas macros especiales allí para evitar tareas repetitivas mientras crea paquetes RPM. Este archivo es importante porque ancla el rpmbuild
entorno con su directorio de inicio.
Empaque su aplicación
Primero, crea un tar
archivo del código fuente en el ~/rpmbuild/SOURCES
directorio:
VERSION=v0.1
NAME=jdumpertools
TARFILE=$(NAME)-$(VERSION).tar.gz
/usr/bin/tar --exclude-vcs --directory ../ --create --verbose --gzip --file $(HOME)/rpmbuild/SOURCES/$(TARFILE) $(NAME)
Normalmente el tar
El archivo contiene scripts y código fuente que compilará dentro del proceso de empaquetado.
A continuación, cree un RPM spec
expediente. De nuevo, rpmdevtools
proporciona una ventaja inicial, como esta:
$ rpmdev-newspec ~/rpmbuild/jose-package.spec
/home/josevnz/rpmbuild/jose-package.spec created; type minimal, rpm version >= 4.16.
$ cat ~/rpmbuild/jose-package.spec
Name: jose-package
Version:
Release: 1%{?dist}
Summary:
License:
URL:
Source0:
BuildRequires:
Requires:
%description
%prep
%autosetup
%build
%configure
%make_build
%install
rm -rf $RPM_BUILD_ROOT
%make_install
%files
%license add-license-file-here
%doc add-docs-here
%changelog
* Sun Oct 03 2021 Jose Vicente Nunez <[email protected]>
-
No se preocupe si no puede entender este archivo ahora. Copie jdumpertools.spec
archivo al ~/rpmbuild/SPECS
directorio:
$ cp -pv jdumpertools.spec ~/rpmbuild/SPECS
Y cree una fuente y un archivo RPM binario:
$ rpmbuild -ba rpmbuild/SPECS/jdumpertools.spec
setting SOURCE_DATE_EPOCH=1609718400
Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.kBlIwO
+ umask 022
+ cd /home/josevnz/rpmbuild/BUILD
+ cd /home/josevnz/rpmbuild/BUILD
+ rm -rf jdumpertools
+ /usr/bin/gzip -dc /home/josevnz/rpmbuild/SOURCES/jdumpertools-v0.1.tar.gz
+ /usr/bin/tar -xof -
+ STATUS=0
+ '[' 0 -ne 0 ']'
+ cd jdumpertools
+ /usr/bin/chmod -Rf a+rX,u+w,g-w,o-w .
+ RPM_EC=0
[...]
Checking for unpackaged file(s): /usr/lib/rpm/check-files /home/josevnz/rpmbuild/BUILDROOT/jdumpertools-v0.1-1.fc33.x86_64
Wrote: /home/josevnz/rpmbuild/SRPMS/jdumpertools-v0.1-1.fc33.src.rpm
Wrote: /home/josevnz/rpmbuild/RPMS/x86_64/jdumpertools-v0.1-1.fc33.x86_64.rpm
Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.uEyCyL
+ umask 022
+ cd /home/josevnz/rpmbuild/BUILD
+ cd jdumpertools
+ rm -rf /home/josevnz/rpmbuild/BUILDROOT/jdumpertools-v0.1-1.fc33.x86_64
+ RPM_EC=0
++ jobs -p
+ exit 0
El resultado final son dos archivos:un RPM fuente y un RPM binario.
Wrote: /home/josevnz/rpmbuild/SRPMS/jdumpertools-v0.1-1.fc33.src.rpm
Wrote: /home/josevnz/rpmbuild/RPMS/x86_64/jdumpertools-v0.1-1.fc33.x86_64.rpm
Qué sucede durante una instalación de RPM
Entonces, ¿qué sucede cuando instala cada uno de sus RPM personalizados?
- Instalar el RPM fuente crea el
tar
archivo y elspec
archivo en surpmbuild
directorio. Esto le permite volver a compilar la aplicación, hacer correcciones a RPMspec
archivo, etc.$ ls rpmbuild/{SPECS,SOURCES} rpmbuild/SOURCES: jdumpertools-v0.1.tar.gz rpmbuild/SPECS: jdumpertools.spec
- Si instala el RPM binario, en realidad está instalando la aplicación:
$ sudo rpm -ihv ~/rpmbuild/RPMS/x86_64/jdumpertools-v0.1-1.fc33.x86_64.rpm Verifying... ################ [100%] Preparing... ################ [100%] Updating / installing... 1:jdumpertools-v0.1-1.fc33 ################ [100%]
- Confirme que el paquete instalado está presente:
$ rpm -qi jdumpertools Name : jdumpertools Version : v0.1 Release : 1.fc33 Architecture: x86_64 Install Date: Sun 03 Oct 2021 06:32:50 PM EDT Group : Unspecified Size : 95002 License : Apache License 2.0 Signature : (none) Source RPM : jdumpertools-v0.1-1.fc33.src.rpm Build Date : Sun 03 Oct 2021 06:27:11 PM EDT Build Host : dmaf5.home URL : https://github.com/josevnz/jdumpertools Summary : Programs that can be used to dump Linux usage data in JSON format. Description : Jdumpertools is a collection of programs used to dump Linux usage data in JSON format to be ingested by other tools. * jdu: Similar to UNIX 'du' command. * jutmp: UTMP database dumper
Nota :Los lectores curiosos probablemente abrieron el Makefile
y vio un objetivo llamado rpm
:
rpm: all
test -x /usr/bin/rpmdev-setuptree && /usr/bin/rpmdev-setuptree|| /bin/mkdir -p -v ${HOME}/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
/usr/bin/tar --exclude-vcs --directory ../ --create --verbose --gzip --file $(HOME)/rpmbuild/SOURCES/$(TARFILE) $(NAME)
/usr/bin/rpmbuild -ba jdumpertools.spec
Este es un atajo conveniente para preparar un rpmbuild
caja de arena, tar
archivos después de compilarlos con make
y empaquetarlos usando rpmbuild
dominio. Siéntete libre de llamar a make rpm
y ver qué pasa.
[ Para obtener más consejos, descargue la hoja de trucos de secuencias de comandos de Bash Shell. ]
Te mostré los comandos y las herramientas que se usan para generar los archivos RPM, pero ahora es el momento de escribir el RPM spec
archivo.
Cree un archivo de especificaciones para las herramientas jdumper
Trabajar con archivos de especificaciones requiere completar varias etiquetas de metadatos y describir cómo compilará o empaquetará la aplicación. Jdumpertools
es una aplicación ANSI C simple, así que descomprima las fuentes, compílelas, cópielas en un área intermedia (~/rpmbuild/BUILDROOT
), y luego empaquetarlos para su distribución.
Primero, eche un vistazo al archivo de especificaciones RPM:
Name: jdumpertools
# TODO: Figure out a better way to update version here and on Makefile
Version: v0.1
Release: 1%{?dist}
Summary: Programs that can be used to dump Linux usage data in JSON format.
License: Apache License 2.0
URL: https://github.com/josevnz/jdumpertools
Source0: %{name}-%{version}.tar.gz
BuildRequires: bash,tar,gzip,rpmdevtools,rpmlint,make,gcc >= 10.2.1
Requires: bash
%global debug_package %{nil}
%description
Jdumpertools is a collection of programs you can use to dump Linux usage data in JSON format to be ingested by other tools.
* jdu: Similar to UNIX 'du' command.
* jutmp: UTMP database dumper
%prep
%setup -q -n jdumpertools
%build
make all
%install
rm -rf %{buildroot}
/usr/bin/mkdir -p %{buildroot}/%{_bindir}
/usr/bin/cp -v -p jdu jutmp %{buildroot}/%{_bindir}
/usr/bin/mkdir -p %{buildroot}/%{_libdir}
/usr/bin/cp -v -p libjdumpertools.so %{buildroot}/%{_libdir}
%clean
rm -rf %{buildroot}
%files
%{_bindir}/jdu
%{_bindir}/jutmp
%{_libdir}/libjdumpertools.so
%license LICENSE
%doc README.md
%changelog
* Mon Jan 4 2021 Jose Vicente Nunez <[email protected]> - 0.1
- First version being packaged
Revisa lo que es importante aquí:
- Los metadatos, incluidos la versión, el nombre y Source0; puedes usar variables o macros
- Descomprima las fuentes en el
%prep
sección usando el%setup
macro (la guía RPM tiene muchos detalles sobre las banderas) - Requisitos de compilación :Debe enumerar las dependencias que necesita para construir el paquete. Estos no se pueden detectar dinámicamente.
- %construir sección:Compilar con
make
- %instalación sección:Copie lo que necesita para que el programa funcione (programa, bibliotecas, etc.)
- %archivos sección:Donde puede especificar si un archivo es un documento (%doc ), archivo de licencia (% de licencia ), o un archivo normal
También importante:
- Desactivé la creación de código de depuración durante el empaquetado con
%global debug_package %{nil}
. - El
changelog
documenta lo que cambió con esta nueva versión del paquete.
Comprueba si hay errores en el archivo de especificaciones con rpmlint
No querrá descubrir por las malas que su RPM no es perfecto. Por lo tanto, es bueno buscar errores obvios o formas de mejorar sus RPM:
$ sudo dnf install rpmlint
Ahora verifique las RPM spec
archivo:
$ rpmlint /home/josevnz/rpmbuild/SPECS/jdumpertools.spec
/home/josevnz/rpmbuild/SPECS/jdumpertools.spec: W: invalid-url Source0: jdumpertools-v0.1.tar.gz
0 packages and 1 specfiles checked; 0 errors, 1 warnings.
La documentación de rpmlint dice que Source0 debe ser una URL bien definida (el valor debe ser una URL HTTP, HTTPS o FTP pública válida). No te preocupes por esta advertencia.
¿Qué pasa con el propio RPM?
$ make rpm
...
$ rpmlint --info ~/rpmbuild/RPMS/x86_64/jdumpertools-v0.2-1.fc33.x86_64.rpm
jdumpertools.x86_64: W: summary-ended-with-dot C Programs that can be used to dump Linux usage data in JSON format.
jdumpertools.x86_64: W: spelling-error %description -l en_US du -> dew, doe, Du
jdumpertools.x86_64: E: description-line-too-long C Jdumpertools is a collection of programs that can be used to dump linux usage data in JSON format, so it can be ingested by other tools.
jdumpertools.x86_64: W: incoherent-version-in-changelog 0.1 ['v0.1-1.fc33', 'v0.1-1']
jdumpertools.x86_64: W: invalid-license Apache License 2.0
jdumpertools.x86_64: W: unstripped-binary-or-object /usr/bin/jdu
jdumpertools.x86_64: W: unstripped-binary-or-object /usr/bin/jutmp
jdumpertools.x86_64: W: unstripped-binary-or-object /usr/lib64/libjdumpertools.so
jdumpertools.x86_64: W: no-soname /usr/lib64/libjdumpertools.so
jdumpertools.x86_64: W: no-manual-page-for-binary jdu
jdumpertools.x86_64: W: no-manual-page-for-binary jutmp
1 packages and 0 specfiles checked; 1 errors, 10 warnings.
Diez advertencias y un error. Algunos son fáciles de arreglar:
- La licencia debe tener un formato específico
- Se requieren páginas man para los programas, así que escribí una muy simple con troff
- Incluir el soname en la biblioteca
Después de las correcciones, solo queda una advertencia:
$ make rpm
...
$ rpmlint --info ~/rpmbuild/RPMS/x86_64/jdumpertools-v0.2-1.fc33.x86_64.rpm
jdumpertools.x86_64: W: spelling-error %description -l en_US du -> dew, doe, Du
The value of this tag appears to be misspelled. Please double-check.
Esta advertencia le advierte que la palabra du
parece estar mal escrito. Sin embargo, es solo una referencia a un comando válido, por lo que puede ignorar la advertencia.
Ahora actualice el RPM con la versión mejorada:
$ sudo rpm -Uhv ~/rpmbuild/RPMS/x86_64/jdumpertools-v0.2-1.fc33.x86_64.rpm
Yo uso el rpm
comando para que sea más obvio que actualicé el paquete desde una versión de disco local en lugar de una nueva versión desde un repositorio. Si lo prefiere, puede hacer lo mismo con dnf
:
$ sudo dnf install --upgrade \
~/rpmbuild/RPMS/x86_64/jdumpertools-v0.2-1.fc33.x86_64.rpm
Lo que aprendiste y lo que sigue
Empaquetar software con RPM parece intimidante al principio, pero con un poco de paciencia, lo logrará en poco tiempo. A medida que encuentre problemas, también encontrará formas adecuadas de mejorar su código. A continuación se presentan algunos recursos y recomendaciones finales:
- Hágase un gran favor y obtenga una copia de la Guía de empaque RPM escrita por Adam Miller, Maxim Svistunov y Marie Doleželová. Es muy completo y bien organizado. En serio, hazlo ahora; es así de bueno.
- La guía RPM Packaging oficial y la guía RPM de Fedora también están llenas de detalles; manténgalos a un marcador de distancia.
- Utilice rpmlint. Se sorprenderá de la cantidad de pequeñas cosas que puede detectar y corregir antes de enviar sus paquetes RPM.
- ¿No es suficiente? Fedora tiene una lista de trucos que puede usar al empaquetar software.
- ¿Sigues teniendo curiosidad? Definitivamente debería echar un vistazo a las pautas de RPM Packaging.