RPM Avanzado
De Wiki de la Comunidad Mandriva
Éste documento cubre varios temas avanzados no necesarios para construir su primer paquete RPM. Antes de seguir, usted debería estar familiarizado con construir RPM's para Mandriva.
[editar] Sistema de menús
El antiguo sistema de menús se detalla en Sistema de menús, mientras que el nuevo sistema XDG (desde Mandriva Linux 2007) se detalla aquí.
[editar] Nombrando un paquete
La norma básica es:
- Utilizar sólo letras minúsculas, formando pañabras separadas con guiones '-'
Por ejemplo: sound-wrapper (no soundwrapper o SoundWrapper)
[editar] Casos especiales
Mezclas de mayúsculas y minúsculas pueden ser aceptadas en algunos casos, cuando ya hay una política para una clase de paquetes, por ejemplo paquetes perl, dado que el nombre refleja el nombre de módulo CPAN.
Tambien cuando el nombre se refiere a un acrónimo, como unixODBC. Sin embargo, siempre se considera más positivo que el nombre comience con una letra minúscula.
[editar] Herramientas Mandriva
Para las herramientas de Mandriva, comience con el prefijo 'drak'.
Por ejemplo: drakconf, drakpxelinux, drakstats
Hay algunas excepciones, como rpmdrake, o harddrake, pero son sólo por razones históricas.
[editar] Cambiar el nombre de un paquete
El renombrado de Rpm no es una operación perfecta, debido a limitaciones del cvs. Si usted decide renombrar un paquete rpm, necesitará mantener la compatibilidad con el antiguo nombre durante algunas entregas (2 ó 3 deberían ser suficientes).
[editar] Cambiando el nombre de un sub rpm
Ésta es la forma más fácil de hacerlo. Todo lo que ha de hacer es renombrar el subpaquete, y entonces añadir:
Provides: antiguonombre Obsoletes: antiguonombre
y todo debería funcionar. El antiguo rpm binario debería ser quitado por el script de subida de carga (upload) y todo irá bien.
[editar] Cambiar el nombre de un rpm (y de su srpm)
Ésto es algo menos suave, dado que perderá la historia en el sistema cvs. Primero, instale el paquete, renombre el fichero de especificaciones, y cambie el nombre en el interior del fichero de especificaciones. Entonces siga el paso anterior, y añada la información 'provides' (proporciona) adecuada.
Verifique que nada se estropea durante la actualización.
Una vez que el paquete está construido, intente quitar o cambiar paquetes que dependan del antiguo nombre, para poder deshacer las secciones Obsoletes y Provides algún día, y para facilitar el trabajo del solucionador de dependencias. Y no olvide añadir ésto en las notas de versión (release notes).
Debería mantener las secciones Obsoletes y Provides durante algunas entregas, dado que hay personas que no se actualizan a todas y cada una de las versiones de la distribución.
[editar] Política con librerías
Consulte la referencia Política con librerías (en inglés)
[editar] Profundizando en los ficheros de especificaciones
[editar] Etiquetas
Hé aquí una lista de otras etiquetas que usted podría ver; algunas las verá a menudo, otras no.
- Prefix: Sirve para reubicar el paquete. NO debería ser usada si su paquete no es reubicable. ¡No se confunda!. Prefix: no define dónde debería ir un paquete. Para especificar su uso: si usted quiere que el prefijo sea /usr, todo lo que ha de hacer es escribir 'Prefix: /usr', y rpm verificará que la ruta de cada fichero que está en el paquete empieza con /usr; si ésta verificación tiene éxito, el paquete será marcado como reubicable.
- Requires: Relaciona lo que necesita el paquete binario para funcionar. Tome nota de que RPM calculará automáticamente las dependencias sobre librerías dinámicas y módulos Perl, así que, para mantener las especificaciones lo más limpias posible sólo debería hacer constar lo que RPM no encuentre automáticamente.
- Buildrequires: Describe lo que es necesario para que éste paquete pueda ser construido. Por ejemplo, para una aplicación basada en ncurses, usted podría poner ncurses-devel. Se puede especificar una versión del paquete usando los operadores =, > o <. Si falta un requerimiento de construcción, el proceso de construcción del paquete fallará.
- BuildConflicts: Qué no debería estar instalado en la máquina para posibilitar la construcción del paquete.
- Provides: Ésto se usa para proporcionar un nombre simbólico (tambien llamado paquete "virtual"). Por ejemplo, apache proporciona "webserver", wu-ftpd y proftpd proporcionan "ftpserver" (de forma que cualquier paquete que necesite un servidor FTP pueda hacer constar "ftpserver" en su campo Requires:).
- Conflicts: Una lista de paquetes que no pueden existir en el sistema al mismo tiempo que éste paquete. Puede especificar versiones usando los operadores =, > y <.
- BuildArchitectures: Especifica arquitecturas determinadas para construir éste paquete, y permite a RPM (¿bail out?) con errores si una de las arquitecturas no está especificada en la lista.
- ExclusiveArch: Sólo se puede construir sobre la arquitectura especificada. Paquetes como MILO, el equivalente de LILO para arquitecturas Alpha, necesitarán ésta especificación.
- ExcludeArch: Excluye las arquitecturas que se especifiquen.
- ExclusiveOS: (realmente no imaginamos por qué querría usted usar ésta) Excluye un programa para un sistema operativo particular.
- Epoch: (reemplaza a Serial) A veces, un esquema de nombrado se ha hecho de una forma incorrecta y el autor quiere volver a una versión anterior. En éste caso, usted necesitará la etiqueta Epoch: con un número. Este número se asumirá sobre la comparación de versión, cuando rpm tenga que averiguar si un paquete es más reciente que otro. Vea la siguiente sección para saber cómo nombrar paquetes entregados a través de pre-versiones.
[editar] Macros
Hay tambien algunas interesantes macros de las que tomar nota. Digamos que usted quiere hacer algo, pero no en todas las arquitecturas. Puede hacer ésto en RPM con las macros condicionales:
%ifarch alpha sparc ppc %patch0 -p1 %endif
La línea del ejemplo indica que sólo se aplique el parche si la arquitectura es alpha, sparc o ppc. Su uso no se limita aquí. Por ejemplo, puede usted incluir ésto en la sección %files si es lo que desea:
Nota: se considera buen comportamiento aplicar un parche a todas las plataformas, a menos que realmente no funcione sobre alguna específica.
[editar] Parámetros de línea de comandos de RPM
Usted ya sabe que puede usar rpm -ba para construir un paquete. Pero tiene más cosas con las que jugar:
- rpm -bp: parar tras completar la sección %prep. Basicamente, descomprime el código fuente y aplica los parches relevantes.
- rpm -bc: parar tras terminar con la sección %build. Generalmente, implica el equivalente a ejecutar make.
- rpm -bi: parar tras completar la sección %install. Bueno, ¿ha de usar -ba para construir de nuevo? ¡No! No todo está perdido. El sistema RPM de Mandriva ha sido especialmente parcheado para permitir a la opción -bi trabajar con --short-circuit, el cual básicamente prosigue el proceso. Así pues, digamos que usted ha cometido un error en la sección %files. Tras arreglarlo, no ha de empezar de nuevo con -ba. Puede simplemente ejecutar rpm -bi --short-circuit file.spec, y luego rpm -ba --short-circuit file.spec para construirlo. Recuerde, ésto es SOLO para usuarios avanzados porque con ésto es fácil construir un fichero de especificaciones estropeado.
- rpm --eval %macroname puede evaluar una macro RPM particular. Parece ser una característica indocumentada de la serie 3.0.x de RPM. Por ejemplo, si deseara evaluar la macro packager, escriba: rpm --eval %packager.
[editar] Temas de dependencias
[editar] Requerimientos automáticos
rpmbuild añadirá automáticamente algunos requerimientos de algunos paquetes que usted compile; por ejemplo, para paquetes perl, intentará encontrar dependencias sobre otros módulos y las agregará como perl(algun::Otro::Modulo). Si usted desea evitar que se añadan algunas de éstas dependencias automáticas, use la macro _requires_exceptions.
Por ejemplo:
%define _requires_exceptions perl(Foo::Bar)\\|perl(Acme::Buffy)
[editar] Lanzando pre-versiones
A veces, los esquemas de nombrado de paquetes están bien, pero rpm se despista. Por ejemplo, con Proftpd, los pre-lanzamientos se nombran con la versión seguida del sufijo "pre" y entonces el número de pre-versión, de ésta forma: 1.2.0pre5. Cuando compara los nombres, rpm piensa que 1.2.0pre5 es más reciente que 1.2.0 (y sabemos que ésto no es así...).
Para permitir actualizaciones a paquetes más recientes, hemos de ayudar a rpm a saber qué paquetes son más nuevos que otros. Podemos usar la etiqueta Epoch: (reemplazando a la etiqueta Serial:) pero se considera una solución "sucia", no es elegante. Tendrá que usar otra convención de nombrado, poniendo el "pre" en la etiqueta 'release'; en nuestro ejemplo usted llamaría el paquete "1.2.0-0.pre5.1mdv". Luego, cuando aparezca la 1.2.0, usted lanzará la "1.2.0-1mdv", y éste paquete será capaz de actualizar al "pre5".
[editar] Alternativas
update-alternatives se describe en Usando Update-Alternatives (en inglés).
[editar] Firmando sus paquetes
La gente con conciencia de seguridad firma sus paquetes, ya que el firmado hace posible verificar que los paquetes no han sido alterados, y para verificar quien los ha creado. GPG (GNU Privacy Guard) ya está incluída en la distribución estándar. Recomendamos que si usted desea firmar su paquete debería usar GPG. RPM soporta tambien PGP (Pretty Good Privacy).
Usted debe empezar por instalar GPG. Ahora, lea la documentación. Como en muchas aplicaciones *nix, ésta viene con buena documentación. Si usted valora su seguridad, podría lamentar despues no haberla leído. Vea un breve conjunto de reglas para empezar (en inglés) y GnuPG - algunos consejos y advertencias (en inglés).
Genere una clave, y entonces extraiga la clave ASCII a un fichero de texto plano:
$ gpg --gen-key
Se le preguntará por el tipo de clave, tamaño de clave, nombre, dirección de correo electrónico y frase de contraseña (¡por favor, vea GnuPG - algunos consejos y advertencias (en inglés)!).
Ahora, agregue 2 líneas a su fichero ~/.rpmmacros:
%_signature gpg %_gpg_name "Su_Nombre_De_Firma"
(No olvide las comillas para delimitar Su_Nombre_De_Firma)
Para firmar sus paquetes durante su construcción, puede usar el argumento --sign. Para agregar una firma a un RPM ya existente, ejecute rpm --addsign fichero.rpm. Para volver a firmar uno ya existente, use la opción --resign.
Para que otros puedan verificar los paquetes, necesitarán una copia de su clave pública GPG. La forma más fácil de hacer ésto es hacer un fichero de clave pública ascii-blindado, puede usted hacerlo con:
$ gpg --list-secret-keys [snip] sec 1024g/1234ABCD 2006-06-24 [expires: 2011-12-13] [snip] $ gpg -ao abc-pub.asc --export 1234ABCD
Debería dejar disponible ésta clave, cargándola a un servidor de clave pública (gpg --send-keys...), o publicándola en un servidor FTP/web. Recuerde que no podrá ser borrada de servidores de clave pública.
Para dar a conocer su nueva clave a rpm, deberá importarla (como root): rpm --import abc-pub.asc
[editar] Más sobre la sección files
A veces, los permisos de los ficheros instalados por RPM no son %defattr(-,root,root) para todos. Puede usted asignar permisos individuales según ficheros con la macro %attr(). %attr sigue un formato similar a %defattr, excepto que %attr se pone delante del nombre del fichero.
Para indicarle a RPM que un fichero particular es un fichero de configuración, sitúe un %config delante del nombre del fichero. De ésta forma, RPM actualizará el fichero, pero guardará una copia del antiguo (con la extensión .rpmsave). La mayoría de veces éste NO ES el comportamiento deseable, porque usted perderá (temporalmente) su apreciada configuración, a costa de otra configuración predeterminada que podría ser más pobre que la que usted desea. Ésto se corrige con %config(noreplace): indica que el fichero del paquete debe ser instalado con la extensión .rpmnew si ya existe en la máquina un fichero modificado con el mismo nombre.
%config(missingok) indica que es necesario que el fichero no exista en la máquina. %config(missingok) se usa frecuentemente con ficheros como /etc/rc.d/rc2.d/S55nombred donde la (no-)existencia del enlace simbólico es parte de la configuración en %post, y puede ser necesario que el fichero deba ser eliminado si el paquete es desinstalado. Este fichero no es necesario ni en el momento de la instalación ni en el de la desinstalación.
La etiqueta %ghost en un fichero indica que éste fichero no se va a incluir en el paquete. Típicamente es usado cuando los atributos del fichero son importantes, pero no su contenido (por ejemplo, un fichero de registro (log)).
[editar] Más sobre subpaquetes
Para separar en subpaquetes usted puede especificar %package foo, donde "foo" es el sufijo que se añadirá al nombre del paquete principal.
Por ejemplo, si su nombre del paquete principal es fred, y tiene una línea %package alice, entonces su subpaquete se llamará fred-alice. Usted necesitará agregar el nombre correspondiente en %description y %files; por ejemplo, %description alice, %files alice.
Si usted no quiere que RPM haga que el subpaquete herede el nombre del paquete principal, puede especificar el argumento -n a %package, como se indica aquí: %package -n misubpaquete. Necesitará añadir -n tambien para todas las demás entradas RPM relevantes, como %description, %files y los scripts RPM. Una de tales potenciales aplicaciones sería la política sobre librerías mencionada anteriormente.
[editar] Qué evitar
Ésta subsección es para constructores de RPM experimentados -- sólo para asegurarse de que no han perdido práctica.
- Evite cualquier referencia a $RPM_SOURCE_DIR. Cuando se usan múltiples ficheros de código fuente, algunas personas tienden a referenciar éstos ficheros usando ésta etiqueta. Ésto debe evitarse y debe ser reemplazado por %{SOURCE2} para Source2: fichero_de_codigo_fuente, por ejemplo. (N del T: Pdte. revisar. Original: Avoid any reference to $RPM_SOURCE_DIR. When using multiple sources, some people tend to reference these sources using this tag. This should be avoided and replaced by %{SOURCE2} for the Source2: source, for example.)
- Evite hacer cosas trucadas/inteligentes/extrañas en el fichero de especificaciones sin documentarlas. Muchas veces, poner un comentario en la línea anterior, con sus iniciales, es muy útil para futuros reempaquetadores, conservando el siguiente estilo:
# (gc) I want to grab the xmms-config built in .., for bootstrapping nicely export PATH=".:$PATH"
[editar] Paquetes específicos de localización
Algunos paquetes sólo trabajan con localizacion(es) especial(es). Por ejemplo, cttex, un programa separador de palabras para el idioma tailandés, no tendrá utilidad si usted no usa éste idioma en su sistema.
Para éstos paquetes necesitará especificar una etiqueta Requires: explícita sobre los correspondientes paquetes de localización (aquí, locales-th). Con ésta información, el instalador será capaz de cambiar los ratios de paquetes de acuerdo a la configuración de internacionalización requerida, de forma que se instalen los paquetes necesarios.
[editar] Mejorando las macros de rpm
Si usted entiende lo que es una macro, sabrá cómo pedir a rpm que haga lo que usted quiera. Aquí se informa sobre algunas macros más o menos internas que usted puede modificar para mejorar algunas cosas
[editar] Macros predefinidas
[editar] Macros de construcción
- %_topdir: el directorio para construir rpms, el usuario debería siempre definirlas en su fichero ~/.rpmmacros. El valor predeterminado es %_usr, tambien conocido como /usr/src/RPM.
- %_rpmdir: es donde se almacenarán los rpms binarios, por defecto es %{_topdir}/RPMS,
- %_srpmdir: es donde se almacenarán los rpms de código fuente, por defecto tiene el valor %{_topdir}/SRPMS,
- %_sourcedir es donde están los ficheros de código fuente, de forma predeterminada es %{_topdir}/SOURCES,
- %_builddir: define dónde se hará la construcción, o sea, el directorio donde los ficheros de fuentes se desempaquetarán y compilarán, por defecto es %{_topdir}/BUILD,
- %_specdir: especifica donde se ubicará el fichero spec cuando se instale un rpm de código fuente, por defecto %{_topdir}/SPECS,
- %_tmppath: es donde se escribirán ficheros temporales, se usa por scripts de construcción y en scripts mdv. Es usado para determinar %buildroot. El valor por defecto es %{_var}/tmp.
- %_rpmfilename: Define el nombre del fichero usado para rpms binarios, por defecto es %{ARQ}/%{NOMBRE}-%{VERSION}-%{RELEASE}.%{ARQ}.rpm. Éste fichero será guardado en %_rpmdir. NOTA: No hay macros para rpms de fuentes. Internamente, rpm siempre dará el nombre NOMBRE-VERSION-RELEASE.src.rpm.
- %__build_cmd: Ésta macro define programas que ejecutarán scripts de construcción. rpm evaluará %__build_cmd SCRIPT_FILE y lo ejecutará. Por defecto es "/bin/sh -e".
[editar] macros rpmdb
- %_dbpath: la ubicación de la base de datos de rpm. Ésta macro queda 'grabada' en el rpm binario en el momento de la construcción. El valor por defecto para Mandriva Linux (y otras distribuciones) es /var/lib/rpm. Puede sobreescribirla para crear y usar otra base de datos. Nota: No la cambie si planea preparar un sistema dentro de un chroot, es mejor usar --root.
[editar] Añadiendo sus propias macros a rpm
Desde la versión 4.4 de rpm, es posible usar comodines en la ruta de búsqueda de ficheros de macros de rpm. Ésto nos da la posibilidad de inyectar nuevas macros simplemente creando un fichero en el directorio adecuado.
Actualmente hay dos formas de añadir una nueva macro:
- pidiendo agregar o modificar una de la configuración básica a los encargados de mantenimiento de rpm-mandriva-setup,
- proporcionándose usted mismo un nuevo fichero de macros.
La primera solución habla por sí misma. Explicaremos la segunda:
Si planea hacer un rpm que proporcione macros, usted debe primero entender que:
- sus macros existirán sólo cuando el rpm que las proporciona sea instalado,
- debe evitar sobreescribir macros; o sea no proporcione una macro que ya sea proporcionada por otro paquete.
En la práctica, usted debe crear un fichero con extensión macros en el directorio /etc/rpm/macros.d/. Aún cuando el nombre del fichero no importe, una buena práctica es usar como nombre %name.macros.
Este fichero se parecerá a otros ficheros de macros:
# Una línea de comentario %nombre_de_la_macro cuerpo_de_la_macro
¡El siguiente paso es poner éste fichero en su paquete, eso es todo!
Debajo hay un completo ejemplo de postgresql, el objetivo es facilitar el empaquetado de herramientas enlazadas a postgres:
mkdir -p %buildroot/%_sys_macros_dir cat > %buildroot/%_sys_macros_dir/%{name}.macros <<EOF %%postgresql_version %{version} %%postgresql_major %{current_major_version} %%postgresql_minor %{current_minor_version} %%pgmodules_req Requires: %{name}-server-ABI = %{current_major_version} EOF
Explicación:
- %_sys_macros_dir es una macro proporcionada por rpm para la ruta /etc/rpm/macros.d
- no olvide usar un "%" doble (o sea, "%%") o la macro será evaluada (lo cual no es lo deseado)
- %{current_major_version} y %{current_minor_version} están definidas en el fichero mismo de especificaciones
- %pgmodules_req permite agregar un requerimiento sobre el módulo postgresql para evitar estropearse en cambios ABI. postgresql-server tiene un 'provide' correspondiente
[editar] La sección %check
Si el código fuente viene con auto-verificaciones (o sea, objetivos "make test" o "make check") puede declararlos en una sección %check falsa entre %build e %install (éste sitio es importante). Luego, para reconstruir el rpm sin ejecutar verificaciones, usted puede hacer:
rpm -ba --define 'check exit 0' foobar.spec
[editar] Paquetes mantenidos en CVS
Algunos paquetes son mantenidos en CVS y no pueden ser cargados (uploaded) con el procedimiento normal. Para éstos paquetes, el fichero .spec empieza con las siguientes dos líneas para advertir al que haya hecho el empaquetado de que se debe usar un procedimiento diferente:
# Changed by Makefile of cvs. # Please change this file only in cvs!
Para actualizar este paquete, por favor use el procedimiento descrito en Guía para RPM desde CVS
[editar] Manejar fácilmente las diferencias entre dos paquetes RPM
La herramienta urpmdiff, disponible en el repositorio 'contrib', permite obtener un informe de diferencias entre dos rpms. Las páginas del manual tienen más información.
[editar] Usando opciones (switches) en los ficheros de especificaciones
Ésta sección detalla cómo usar opciones en los ficheros de especificaciones para facilitar la construcción de un paquete rpm alternativo, con más o menos funcionalidades.
[editar] Reconstruir un rpm con una opción activada
Reconstruir un rpm es sencillo. Todo lo que usted necesita es descargar el srpm y ejecutar rpm --rebuild mirpm.src.rpm.
Para ver si un paquete puede ser reconstruido con opciones, puede mirar la descripción o documentación, o bien revisar el fichero spec. No hay ningún mecanismo construido para hacer ésto, pero es una práctica común añadirlo en la descripción y agregar un fichero llamado README.mdk para explicar la opción y qué valor ha sido elegido por defecto.
Si el paquete es reconstruible (como postfix), todo lo que ha de hacer es: rpm --rebuild --with opcion mirpm.src.rpm.
[editar] Añadiendo opciones a los ficheros de especificaciones
Una opción requiere unas pocas macros en los ficheros de especificaciones.
# define los valores predeterminados %define with_FEATURE 1 # si se usa la opción --without %{?_without_feature: %{expand: %%global with_FEATURE 0}} # si se usa la opción --with %{?_with_feature: %{expand: %%global with_FEATURE 1}}
Luego usted puede usar la siguiente construcción en su fichero de especificaciones:
%if %{with_FEATURE} # hacer alguna cosa para habilitar la funcionalidad %endif
[editar] Algunos ejemplos
Aquí hay una lista de unos pocos rpms de Mandriva Linux que usan opciones, donde puede usted mirar para ver la implementación adecuada:
- postfix
- samba
- openssh
[editar] Nombrando una opción
Si usted planea añadir una opción, por favor mire en ésta lista para mantener consistencia en el método (y agregue los suyos):
- mysql
- ldap
- sasl
- pgsql (soporte para postgresql)
- pam
- tls (ssl)
[editar] Describiendo los cambios
Para ayudar a otros usuarios con intención de reconstruir, usted debería describir los cambios en la descripción del paquete (http://archives.mandrivalinux.com/cooker/2005-01/msg02836.php). El formato aún no ha sido decidido, pero debería proporcionar las opciones que podrían ser empleadas, una descripción de las opciones, y cuales han sido las opciones predeterminadas en el paquete actual (http://archives.mandrivalinux.com/cooker/2005-01/msg02837.php).
Puede usted tambien añadirlas en un fichero situado en %doc (algo así como README.mdk, pero el nombre aún no ha sido decidido).
[editar] Discusiones desarrolladas sobre éste asunto
- Estandarización de la descripción del paquete (http://archives.mandrivalinux.com/cooker/2005-01/msg01237.php)
[editar] Para convertirse en un Jedi, use Emacs. Debe hacerlo
En resumen, Emacs puede automatizar mucho trabajo con un fichero de configuración apropiado. Un buen comienzo es rpm-spec-mode.el, que ahora es proporcionado por el paquete rpm-build (solía ser el único de Chmouel).
Una vez instalado, además de un bonito esquema de colores para la sintaxis, usted podrá incrementar la etiqueta 'release' simplemente con la combinación de teclas C-c r, añadir una nueva entrada del registro de cambios (changelog) (con su nombre, dirección de correo electrónico, etiquetas de versión y release correctas) con la combinación C-c e; ¡podrá incluso ver los parches comprimidos (siempre que tenga instalado jka-compr y ffap) sin tropiezos!. M-x rpm-change-group permite añadir/modificar un grupo recorriendo la lista de grupos disponibles. Y mucho más...
Puede usted personalizar Emacs en gran medida cuando conozca un poco de Emacs-Lisp: Vea en personalización del modo especificaciones de RPM (en inglés) algunas funciones útiles.
[editar] Glosario
- Paquete reubicable - Es un paquete que podría ser instalado en un lugar diferente. Según rpm.org, ésto es útil si el lugar original donde ha de ser instalado no tiene espacio suficiente (en caso de distribuir los directorios de sistema en diferentes particiones, por ejemplo, /usr en una partición distinta de la de /).