Icono del sitio Shakaran

Crear paquetes DEB de código Python en Ubuntu


La mayoría de desarrolladores de Python suele empaquetar sus programas en archivos .deb instalables para Ubuntu.

He buscado información para realizar esta tarea, pero he comprobado que la información está bastante disgregada y a veces incompleta o sin traducir. Por tanto, voy a intentar hacer una guía recopilando extensamente todas las opciones a tener en cuenta para empaquetar un programa en Python (aunque fácilmente es extrapolable a otros lenguajes).

Paso 1 – Instalando los paquetes necesarios

Necesitamos instalar los siguientes paquetes: build-essential, automake, gnupg, lintian, fakeroot, pbuilder, devscripts, debhelper y dh-make

sudo apt-get install build-essential automake gnupg lintian fakeroot pbuilder devscripts debhelper dh-make

Paso 2 – Crear un directorio de trabajo

Para organizar el empaquetado crearemos un directorio en el que haremos todas nuestras modificaciones, generalmente se suele nombrar en inglés como “sandbox” (caja de arena, por aquello de dibujar algo en la arena y luego deshacerlo).

Mediante terminal:

mkdir sandbox

Entramos al directorio:

cd sandbox

Paso 3 – Nombrar correctamente el paquete

Antes de empaquetar el nombre de directorio que contiene el programa debe cumplir cierta regla:

Nombre de programa + guión + versión

Por ejemplo: si tenemos un programa llamado programator en la versión 0.1.32, el nombre para el directorio sería programator-0.1.32

Crearemos el directorio con:

mkdir programator-0.1.32

Cuando hayas hecho esto, mete los archivos de programa dentro, por ejemplo si tuvieras un archivo programator.py y un directorio llamado data, donde guardas las imágenes de iconos del programa, etc.

Es importante el nombre del programa, si el nombre del programa está formado por varias palabras, contráelas a una palabra o haz una abreviatura. Por ejemplo, el paquete del programa «el editor para X de José» se podría llamar josedx o jle4x, o lo que decidas, siempre y cuando no se exceda de unos límites razonables, como 20 caracteres.

Paso 4 – Comprimir el directorio del programa

Para pasos sucesivos necesitamos comprimir el directorio del programa con el siguiente comando:

tar czf programator-0.1.32.tar.gz programator-0.1.32

Paso 5 – Respaldar el programa original

Es importante hacer una copia del código fuente original, por si erramos en el proceso o simplemente queremos deshacer cambios.

Para ello, es importante asociarnos bien con la terminología relacionada con el empaquetamiento.

Normalmente, el código de desarrollo que procede de otra fuente superior a la original, en inglés se le llama “upstream“. Por contra, el término “downstream” es el empaquetador de software que trabaja a partir de otro desarrollo superior.

Por ejemplo: la mayoría del software de Ubuntu viene directamente de Debian, por lo que Debian es considerado upstream de Ubuntu. la mayoría de los paquetes de Debian vienen a su vez de otros proyectos, como GNU, Linux, KDE y GNOME, que son a su vez upstream de Debian.

Pero también puedes verlo de la forma contraría. Como que Linux tiene el downstream de Debian y este a su vez de Ubuntu.

El upstream suele tener el siguiente formato:

<nombrepaquete>_<version>.orig.tar.gz

Observa que se utiliza un guión bajo en el nombre y que se comprime el directorio en formato Gzip. El guión bajo es importante porque las herramientas de empaquetado buscarán un nombre de archivo con ese formato exacto, asi que si te equivocas la herramienta asumirá que no hay paquete original de código fuente y el paquete se construirá como un paquete de Debian nativo.

En nuestro ejemplo sería: programator_0.1.32.orig.tar.gz

Podemos reutilizar el archivo comprimido anterior y hacer una copia, puesto que solo varía el nombre, luego:

cp programator-0.1.32.tar.gz programator_0.1.32.orig.tar.gz

Otro asunto importante es que puedes construir dos tipos de paquetes: fuentes y binarios.

Un paquete fuente contiene el código que puedes compilar en un programa.

Un paquete binario contiene sólo el programa terminado.

¡No mezcles los términos como «fuentes de un programa» y el «paquete fuente de un programa»!

Paso 6 – Crear el directorio debian

El directorio debian es donde se almacenará toda la información de empaquetado.

Con ello conseguimos separar la parte de información de empaquetado de la parte de los archivos del programa fuente.

Utilizaremos la herramienta dh_make para que haga el trabajo por nosotros.

Con dh_make tenemos los siguientes parámetros de configuración:

Usa el tipo de <licencia> para el archivo de copyright. <licencia puede ser gpl, gpl2, gpl3, lgpl, lgpl2 lgpl3, artistic, apache or bsd.

Usa <dirección> como dirección de correo electrónico del campo Maintainer (desarrollador) para el archivo debian/control.

Establece automáticamente la clase del paquete a biblioteca, saltando la pregunta.

Establece automáticamente la clase del paquete binario único, saltando la pregunta.

Establece automáticamente la clase del paquete a independiente de la arquitectura, saltando la pregunta.

Establece automáticamente la clase del paquete a binario múltiple, saltando la pregunta.

Dirección de correo electrónico para usar en las entradas de control y changelog.

Tu nombre completo, por ejemplo, “José Sánchez Gijón” que aparecerá en las entradas de control y changelog.

Dirección de correo electrónico para usar en las entradas de control y changelog, solo usado si DEBMAIL no esta establecido.

Debian usa el término desarrollador («maintainer») para la persona que hace paquetes, autor original («upstream author») para la persona que hizo el programa, y desarrollador original («upstream maintainer») para la persona que actualmente mantiene el programa fuera de Debian. Generalmente el autor y el desarrollador fuente son la misma persona – y algunas veces incluso el desarrollador es el mismo.

Existen algunas opciones más que puedes ver con man dh_make pero generalmente estas suelen ser todas las necesarias para un empaquetado básico.

Así, por ejemplo utilizaremos la licencia gpl3 y la opción single ya que tenemos un binario sólo y un email y nombre ficticios. Nos vamos al directorio del programa fuente:

cd programator-0.1.32

Exportamos variables:

export DEBEMAIL=programator@gmail.com DEBFULLNAME="Jose Sánchez Gijón"

Y ejecutamos el comando de dh_make:

dh_make -e programator@gmail.com -c gpl3 -s

Nota: es necesario poner dos veces el correo electrónico (tanto en DEBEMAIL como en la opción -e) ya que cada una tiene una utilidad distinta y el correo puede ser diferente. Pero si usas el mismo email, puedes usar la variable DEBEMAIL para ahorrartelo por ejemplo:

dh_make -e $DEBEMAIL -c gpl3 -s

Ahora ya tendremos creado el directorio debian/

Paso 7 – Eliminar plantillas y editar archivos de empaquetado

En el directorio debian, se crean por defecto archivos de plantilla con extensión .ex. Generalmente, para programas simples no suelen ser necesarios y podemos eliminarlos con los siguientes comandos:

Nos vamos al directorio debian:

cd debian

Borramos las plantillas

rm *.ex *.EX

Aún quedarán algunos archivos adicionales en el directorio debian que pueden ser innecesarios:

Por tanto, los archivos que realmente nos pueden ser importantes (para construir un paquete básico) son los siguientes archivos: changelog, compat, control, copyright, y rules en el directorio debian.

Paso 8 – Configurando archivo changelog

El archivo changelog es una lista de cambios hechos en el programa para cada versión. Tiene un formato específico en el que se escriben el nombre de paquete, version, distribución, cambios y quien hizo dichos cambios en un determinado momento.

Además si tenemos una llave GPG, podemos asegurar que el nombre y email que aparecen en el changelog son los mismos que los dados por la llave GPG.

Una posible plantilla de changelog sería:

paquete (version) distribución; urgency=urgencia

  * detalles de cambios
    más detalles de cambios
  * incluso más detalles de cambios

 -- nombre del mantenedor < correo electrónico >[dos espacios]  fecha

El formato (especialmente la fecha) es importante. La fecha debe estar en formato RFC822 que puedes conseguir con usando el comando date -R.

Los puntos menores se indican con un guión “-“, mientras que los puntos con mas importancia usan el asterisco “*”.

Para nuestro paquete de ejemplo programator sería:

programator (0.1.32-0ubuntu1) jaunty; urgency=low

   * Nueva liberación corrigiendo muchos fallos y mejoras.

 -- Jose Sánchez Gijón < programator@gmail.com>  Wed,  27 Aug 2009 22:38:49 -0700

Si has observado bien, habrás visto que se ha añadido -0ubuntu1 a la versión. Eso es porque es la versión de la distribución que se usa para empaquetar actualizaciones (por ejemplo versiones de paquetes que arreglan fallos) pero son versiones que contienen el mismo código que la versión original.

Por ejemplo si fuese un fallo específico de Ubuntu que se arregla para la versión de Ubuntu.

Ubuntu y Debian tienen ligeras diferencias en las plantillas de empaquetado de versiones para evitar conflictos con los paquetes que proceden de la misma versión de código fuente. Si por ejemplo un paquete de Debian ha sido cambiado en Ubuntu, se añadirá ubuntuX (donde X es el número de revisión de Ubuntu) al final de la versión de Debian.

Si la versión del paquete de Debian programator 0.1.32-1 es cambiada por Ubuntu, el nombre de versión pasaría a ser programator 0.1.32-1ubuntu1. Pero si el paquete para la apliación no existe en Debian, entonces la revisión de Debian seria cero, por tanto programator 0.1.32-0ubuntu1.

Por otro lado el comando dch (tambien conocido como debchange, del paquete devscripts) puede usarse para editar el changelog y actualizará la fecha automáticamente:

dch -i

Es aconsejable ejecutar dicho comando estando en el directorio de fuentes (y no un subdirectorio) ya que el programa abrirá el changelog para modificarlo y crear una nueva línea. Por su parte, el parámetro “-i” incrementará el número de versión del paquete y además creará una entrada nueva que podremos editar.

La utilidad del comando radica principalmente en controlar los cambios de una versión a otra, pero tambien dentro de la propia versión del paquete.

Por ejemplo, al debianizar programator 0.1.32 en el changelog nos pondrá la versión “0.1.32-1” indicando que es la primera versión del paquete, al hacer “dhc -i” pasaría a ser la “0.1.32-2”.

Por otro lado, los valores de urgencia son soportados por los gestores de paquetes, pero no son usados en Debian. La urgencia afecta a como de rápido el paquete será considerado para la inclusión en la distribución y le da una indicación de la importancia de los fallos arreglados. Valores como “critical” o “emergency” son tratados por igual.

Normalmente para cambios que incluyen una funcionalidad poco importante suele ser “low” (baja) y si se suelen arreglar fallos importantes es “high” (alta).

Si deseas más información al respecto consulta la política de cambios de Debian

Paso 9 – Configurando archivo control

El archivo de control contiene información para los gestores de paquetes (como apt-get, synaptic, adept), tiempo de compilación, información del mantenedor y mucho más.

Un ejemplo para nuestro programa:

Source: programator
Section: devel
Priority: optional
Maintainer: Jose Sánchez Gijón < programator@gmail.com>
XSBC-Original-Maintainer: Jose Sánchez Gijón < programator@gmail.com>
Standards-Version: 3.7.3
Build-Depends: debhelper (>= 5)
Homepage: http://www.programator.com/software/programator/

Package: programator
Architecture: any
Depends: ${shlibs:Depends}
Description: El clásico paquete de prueba para un ejemplo
 El paquete programator, es el paquete de prueba para hacer buenos
 ejemplos de software, a ser posible software libre.

El primer párrafo da información sobre el código fuente del paquete. A continuación se detallan el resto de líneas:

El segundo párrafo es para el paquete binario que se construirá a partir del código fuente. Si existen múltiples paquetes binarios que son construidos desde el código fuente, habrá una sección para cada uno. La explicación para cada línea:

Paso 10 – Configurando archivo copyright

Es el archivo que proporciona la información sobre copyright. Generalmente esta información se encuentra en el archivo COPYING en el directorio del programa fuente. Este archivo debe incluir la información de los nombres de autores y el empaquetador, la URL desde la que viene el código fuente y una línea de Copyright con el año y el propietario del Copyright. Un ejemplo:

This package was debianized by {Tu nombre} < tu dirección de correo electrónico>
{Fecha}

It was downloaded from: {URL de la página web} 

Upstream Author(s): {Nombres y direcciones de correo de los autores}

Copyright:
        Copyright (C) {Años} by {Autores} {direccion de correo}

License:

        {Añadir el texto de la licencia aqui. Para licencias GNU añadir
        el encabezado y un enlace al archivo correspondiente en /usr/share/common-licences.}

Packaging:
        Copyright (C) {Años} by {Tu nombre} < tu dirección de correo electrónico>
        released under {la licencia que elegiste para empaquetar}

Para el programa de ejemplo:

This package was debianized by José Sanchéz Gijón < programator@gmail.com>
27 Aug 2009 16:36:39 +0200

It was downloaded from: http://www.programator.com/software/programator/ 

Upstream Author(s): José Sanchéz Gijón < programator@gmail.com>

Copyright:
        Copyright (C) 2009 by José Sanchéz Gijón < programator@gmail.com>

License:

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This package is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see .

On Debian systems, the complete text of the GNU General
Public License version 3 can be found in `/usr/share/common-licenses/GPL-3'.

The Debian packaging is:

    Copyright (C) 2009 by José Sanchéz Gijón < programator@gmail.com>
and is licensed under the GPL version 3, see above.

Paso 10 – Configurando archivo rules

Uno de los archivos que necesitamos mirar es rules. Este archivo hace la mayoría del trabajo para crear el paquete.

En realidad, es un archivo de Makefile con los objetivos para compilar e instalar la aplicación que despues creará el archivo .deb para los archivos intalados.

Las reglas definiran la forma en la que se compilará y empaquetará nuestro programa (puedes añadir todas las opciones que normalmente añadirías al ./configure de un programa, opciones de compilación, optimizaciones, etc).

Normalmente no es necesario hacer cambios aqui para paquetes básicos, pero debes tenerlo en cuenta si tu proyecto lo requiere.

Yo todavía no soy un experto en esta materia (puede que haya fallos en lo siguiente), pero bajo mis observaciones, he comprobado que algunas de las siguientes modificaciones son las más se realizan comunmente (cambia programator por el nombre de tu aplicación):

Paso 11 – Configurando archivo dirs

Este archivo es el encargado de crear los directorios en caso de que no existan (de ahí que quizas en el paso anterior haya algunas líneas que sobren, pero aun no lo he comprobado). Supuestamente todos los directorios que se vayan a crear durante el empaquetamiento deben indicarse en este archivo.

Los más comunes para nuestro ejemplo serían:

usr/bin
usr/share/programator
usr/share/applications

Paso 12 – Configurando archivo README.Debian

No confundir este programa con README.source como ya indique antes. Este sera el README de Debian, no el del empaquetado para aquellos que quieran modificarlo.

Un ejemplo de fichero creado originalmente en nuestro programa:

    README.Debian
    
    programator for Debian
-----------------



 -- José Sanchéz Gijón   Fri, 28 Aug 2009 10:13:44 +0200
 

Que podríamos cambiar a:

    README.Debian
    
    programator for Debian
-----------------

Comentarios, mejoras, fallos y cariño son bienvenidos en http://www.programator.com/software/programator/

 -- José Sanchéz Gijón   Fri, 28 Aug 2009 10:13:44 +0200

Paso 13 – Generar el paquete .deb

Parece que hay demasiados pasos, pero realmente son bastante sencillos y haciendolo un par de veces puedes tener un empaquetado en 15 minutos. Ahora vamos con la parte más interesante de este artículo.

Después de todo este tedioso proceso simplemente hay que ejecutar el siguiente comando (desde el directorio de fuentes, no el de /debian):

dpkg-buildpackage -rfakeroot -us -uc

Es importante NO ejecutar este comando nunca como root, ya que podríamos crear conflictos como por ejemplo en los permisos de los archivos movidos por rules (recordad que es en realidad un Makefile) o en el firmado de paquetes.

Para tener privilegios root donde es necesario acudimos a la opción -rfakeroot que es dada por el paquete fakeroot, de esta manera podemos actuar con privilegios sin crear conflictos.

La opción -us es para no firmar el paquete fuente y la opción -uc es para no firma el archivo .changes de cambios. Normalmente es más cómodo no firmar el paquete en la generación y luego si se desea firmarlo (o si la generación y la firma se lleva a cabo por distintas personas).

El firmado es opcional, pero si deseas autentificar tu paquete y tener mayor seguridad, lee el último paso de este artículo.

Paso 14 – Firmado GPG de paquetes .deb

El firmado parece algo complicado, pero realmente son unos pocos comandos y normalmente solo hay que hacer este paso una vez.

Si aun no tienes un clave GPG, puedes crear una facilmente con el siguiente comando:

$ gpg --gen-key

En el proceso elige la opción 1 (DSA y ElGamal), de tamaño 2048 y 0 para que la clave no daduque nunca.

Luego da tus identificadores como el nombre real, comentario y dirección de correo.

Por ejemplo:
Nombre y apellidos: José Sanchéz Gijón
Dirección de correo electrónico: programator@gmail.com
Comentario: My GPG key

Despues se generará la clave (es necesario hacer alguna tarea como mover ventanas o abrir alguna apliación, para que se genere aleatoridad, si no te saldrá un mensaje y tendrás que esperar unos segundos para que intente generar la clave de nuevo.

Por ejemplo una posible salida sería (la clave es ficticia):

$ gpg --gen-key
gpg (GnuPG) 1.4.9; Copyright (C) 2008 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Por favor seleccione tipo de clave deseado:
   (1) DSA y ElGamal (por defecto)
   (2) DSA (sólo firmar)
   (5) RSA (sólo firmar)
¿Su elección?: 1
El par de claves DSA tendrá 1024 bits.
las claves ELG-E pueden tener entre 1024 y 4096 bits de longitud.
¿De qué tamaño quiere la clave? (2048) 
El tamaño requerido es de 2048 bits
Por favor, especifique el período de validez de la clave.
         0 = la clave nunca caduca
        = la clave caduca en n días
      w = la clave caduca en n semanas
      m = la clave caduca en n meses
      y = la clave caduca en n años
¿Validez de la clave (0)? 0
Key does not expire at all
 nunca caduca
¿Es correcto (s/n)? s

Necesita un identificador de usuario para identificar su clave. El programa
construye el identificador a partir del Nombre Real, Comentario y Dirección
de Correo Electrónico de esta forma:
    "Heinrich Heine (Der Dichter) "

Nombre y apellidos: José Sanchéz Gijón
Dirección de correo electrónico: programator@gmail.com
Comentario: My GPG key
Está usando el juego de caracteres `utf-8'.
Ha seleccionado este ID de usuario:
    "José Sanchéz Gijón (My GPG key) "

¿Cambia (N)ombre, (C)omentario, (D)irección o (V)ale/(S)alir? V
Necesita una frase contraseña para proteger su clave secreta.

Es necesario generar muchos bytes aleatorios. Es una buena idea realizar
alguna otra tarea (trabajar en otra ventana/consola, mover el ratón, usar
la red y los discos) durante la generación de números primos. Esto da al
generador de números aleatorios mayor oportunidad de recoger suficiente
entropía.
+++++.+++++.+++++...++++.+++++.+++++.+++++.+++++++++++++++.++++++++++..+++++++++++++++++++..+++++.+++++.+++++.++++++++++..++++++++++...+++++.++++++++++>+++++++++................................+++++

No hay suficientes bytes aleatorios disponibles. Por favor, haga algún
otro trabajo para que el sistema pueda recolectar más entropía
(se necesitan 283 bytes más).
Es necesario generar muchos bytes aleatorios. Es una buena idea realizar
alguna otra tarea (trabajar en otra ventana/consola, mover el ratón, usar
la red y los discos) durante la generación de números primos. Esto da al
generador de números aleatorios mayor oportunidad de recoger suficiente
entropía.
++++++++++++++++++++.+++++.++++...+++++++++++++++++++++++++.++++++++++...++++++++++...+++++......++++++++++++++.+++++.++++++++++.+++++++++++++++++++++++++++++++++++>++++++++++>.++++++....>+++++........< ..+++++...........>+++++...< .+++++......>...+++++..< +++++..........+++++^^^^^
gpg: clave 4DEEE67E marcada como de confianza absoluta
claves pública y secreta creadas y firmadas.

gpg: comprobando base de datos de confianza
gpg: 3 dudosa(s) necesarias, 1 completa(s) necesarias,
modelo de confianza PGP
gpg: nivel: 0  validez:   1  firmada:   0  confianza: 0-, 0q, 0n, 0m, 0f, 1u
pub   1024D/4DEEE67E 2009-08-28
      Huella de clave = F154 9A31 C480 9E5B CD82  41E1 5984 5A83 1DEE E13E
uid                  José Sanchéz Gijón (Mi GPG Key) 
sub   2048g/2FDE8A53 2009-08-28

Lo que realmente nos interesa ahora es el número que aparece despues de 1024D/ en este caso 4DEEE67E.

Si has hecho este proceso pero no has apuntado este número, no importa porque siempre puedes consultarlo con el comando:

$ gpg --list-secret-keys

Por ejemplo:

$ gpg --list-secret-keys
/home/programator/.gnupg/secring.gpg
---------------------------------
sec   1024D/4DEEE67E 2009-08-28
uid                  José Sanchéz Gijón (Mi GPG Key) 
ssb   2048g/2FDE8A53 2009-08-28

Como truco adicional, si quieres exportar tu clave para que en todas las sesiones de terminal este presente, puedes utilizar los siguientes comandos poniendo el valor de tu clave:

export GPGKEY=4DEEE67E
killall -q gpg-agent
eval $(gpg-agent --daemon)
source ~/.bashrc

Una vez hecho esto, seguramente no necesites hacerlo muchas veces más, ya que generalmente es suficiente con tener una misma clave.

Por tanto, vamos a firmar el código fuente y el archivo .changes. Para ello, necesitamos tener instalado el paquete debsign:

sudo apt-get install debsign

Y para el programa de ejemplo (es necesario que la clave este pegada a la opcion -k, sino no funcionará):

debsign -k4DEEE67E programator_0.1.32-0ubuntu1.dsc
debsign -k4DEEE67E programator_0.1.32-0ubuntu1_i386.changes

¿Necesitas practicar?

Si ya has “debianizado” tu programa y sigues con ganas de empaquetar, puedes buscar paquetes para “adoptar” en el listado de paquetes en adopción de Debian o bien en el listado de paquetes solicitados de Debian o bien en Ubuntu.

Bibliografía

Enlaces fuente para la bibliografía:

Actualización

A falta de una herramienta mejor, he creado un pdf del artículo a partir de una web online para aquellos que deseen leerlo offline o guardarlo para futuros usos:

Descargar pdf del artículo


Salir de la versión móvil