Personal Website

My Web: MindEchoes.com

Sunday, March 21, 2010

Instalador DEB para programas Python

Bueno, trabajando con PyTv quise hacer un paquete DEB para que sea mas fácil instalar el programa, y acá dejo los pasos que seguí para poder hacerlo:

Primero es necesario tener instalados los siguientes paquetes: dpkg-dev y dh-make, los cuales pueden instalarse de la siguiente forma:

sudo apt-get install dpkg-dev dh-make

Para ir dejando las cosas claras, vamos a tomar la carpeta "pytv-series" como la carpeta donde actualmente estaría contenido el programa que se ha desarrollado (los nombres de las carpetas, etc. deben ser adaptados según el programa para el que se este haciendo el paquete, los nombres que aparecen acá son a modo de ejemplo).
Supongamos que la carpeta del programa desarrollado y las carpetas que vamos a crear parten del "home", por una simple cuestión de simplicidad, luego simplemente habría que reemplazar "home" por la ruta a donde se tenga realmente las carpetas.

1) Primero vamos a necesitar crear una carpeta donde trabajar:
~$ mkdir deb
~$ cd deb
Luego una vez dentro de esa carpeta, procedemos a crear una carpeta con el nombre de nuestro programa y la versión:
~$ mkdir pytv-1.2
En este último directorio creado debemos copiar una versión empaquetada de nuestro programa, la cual podemos realizar de la siguiente forma:

(Accedemos a la carpeta de nuestro programa)
~$ cd /home/pytv-series
~$ tar cfzv pytv-1.2.tar.gz *
~$ cp * /home/deb/pytv-1.2
~$ cd /home/deb/pytv-1.2
("pytv-series" es la carpeta donde esta nuestro código fuente y "pytv-1.2" es la carpeta creada para este ejemplo donde vamos a poner todos los archivos necesarios para crear el paquete DEB. El empaquetado creado con "tar" debe llevar el nombre y versión del programa para el que lo queremos hacer)
Los fuentes que fueron empaquetados dentro de "pytv-1.2.tar.gz" también es necesario copiarlos dentro de la misma carpeta ("/home/deb/pytv-1.2")

2) Dentro de nuestra carpeta de trabajo donde quedamos después del último comando ejecutado, utilizamos el comando dh_make (el cual es uno de los programas instalados al iniciar) de la siguiente forma:

~$ sudo dh_make -e diego.sarmentero@gmail.com
      -f pytv-1.2.tar.gz -c GPL

Este comando se encarga del proceso de "debianización" del directorio. Los parámetros especificados son los siguientes:

  • -e diego.sarmentero@gmail.com : es el e-mail del creador del programa
  • -f pytv-1.2.tar.gz : indicamos el nombre del paquete comprimido que contiene nuestro programa
  • -c GPL : indicamos la licencia del programa
Luego de haber ejecutado el último comando, podremos ver que se ha creado una carpeta llamada "debian" en el directorio en el que nos encontramos.

3) Entramos dentro de la carpeta "debian" y nos encontramos con una serie de archivos, algunos de ellos no serán de utilidad para nuestro propósito, por lo que podemos eliminarlos:

(dentro de la carpeta "debian"):
~$ rm *.ex *.EX
Ahora procedemos a editar los demás archivos para nuestro programa:

CHANGELOG
Simplemente (si no tenemos historiales de cambios o cosas asi) es necesario colocar la versión del programa y el nombre del autor:


pytv (1.2) stable;


-- Diego Sarmentero Fri, 05 Mar 2010 17:50:57 -0300

COMPAT
No es necesario hacer ninguna modificación con este archivo (por lo menos yo no lo hice :P), así que lo podemos dejar así como esta.

CONTROL
Este es uno de los mas importante, ya que establece las categorias, dependencias, y otras configuraciones del programa. Para PyTv la configuración quedo como sigue y se explica a continuación:


Source: pytv
Section: utility
Priority: extra
Maintainer: Diego Sarmentero
Build-Depends: debhelper (>= 7)
Standards-Version: 3.8.1
Homepage:


Package: pytv
Architecture: any
Depends: python (>=2.5.2-1ubuntu1), python-qt4 (>=4.4.4-2), sqlite (>=2.8.17-6build1), python-beautifulsoup (>=3.1.0.1-2)
Description: PyTv: Tv Series notification utility

Los detalles a configurar mas relevantes son:

  • Source: (OPCIONAL) el nombre del paquete fuente del que proviene él paquete binario, en caso de que ambos sean distintos. En este caso se podría omitir pero tampoco hace mal dejarlo.
  • Section: (OPCIONAL) define la categoría del paquete. Una forma simple de verlo es que dentro de esta categoría lo podremos encontrar en el menú de Aplicaciones. Otras categorías son: "games", "devel", "text", "video", "sound", etc.
  • Maintainer y Homepage: Es la información del desarrollador (o el que mantenga) el programa y la web del mismo programa
  • Package: (CAMPO NECESARIO) determina el nombre del paquete.
  • Architecture: La arquitectura para la que se compiló el paquete. Arquitecturas comunes son ‘i386’, 'amd64', ‘m68k’, ‘sparc’, ‘alpha’, ‘powerpc’, etc. La opción "all" es para paquetes independientes de la arquitectura como lo son los scripts de Perl o la documentación.
  • Depends: Este quizás sea el mas importante de configurar si nuestro programa necesita de alguna librería adicional o lo que fuera. Lo que necesitamos poner es el nombre del paquete con el que se tiene dependencia y a partir de que versión (según con la que hayamos trabajado para hacer el programa). Es importante respetar el formato que se muestra arriba. Los paquetes y sus versiones se pueden consultar en el Gestor De Paquetes.
  • Description: en la documentación de figura como NECESARIO, así que por las dudas poner aunque sea una pequeña descripción del proyecto... no cuesta nada jeje
COPYRIGHT
Para este archivo solo es necesario modificar el nombre del autor y la url de la página del proyecto.

DIRS
Contiene la ruta de los directorios que el paquete necesitará para para instalar el programa.
En el caso de PyTv:

usr/bin
usr/share/pytv
usr/share/applications

En la segunda linea sería necesario reemplazar "pytv" por el nombre del paquete de la aplicación con la que se esta trabajando.

DOCS
En mi caso este archivo permaneció vació, pero si hay alguna documentación referente al proyecto que se pueda agregar, ese podría ser un lugar donde colocarla.

README.Debian
En él ponemos comentarios que consideremos importantes para quien vaya a utilizar el programa. Este archivo no es obligatorio, en mi caso agregue simplemente lo siguiente:

pytv for Debian/Ubuntu
----------------------

http://code.google.com/p/pytv-series/

-- Diego Sarmentero Fri, 05 Mar 2010 17:50:57 -0300

RULES
Este archivo tiene una configuración un tanto extensa, aunque no complicada, yo recomendaría simplemente descargar el ejemplo al final del Post y utilizar como base el archivo RULES presente en el zip.
La única sección que sería necesario modificar es: "install: build", cambiando donde figure "pytv" por el nombre de la aplicación con la que se esta trabajando.

4) Luego de esto dejamos la carpeta debian y volvemos a la carpeta pytv-1.2 que contenia a debian.
Un detalle importante es en cuanto al manejo de imagenes y archivos creados por el programa.
En el caso de PyTv al desarrollar las imagenes eran accedidas a través de rutas relativas al directorio donde se esta ejecutando el programa, y SQLite utilizaba también un archivo para la Base de Datos accediendo a él de forma relativa al directorio actual:

#Cargando imagen
pixmap = QtGui.QPixmap('pytv.png')
#Accediendo a la Base de Datos
import sqlite3 as dbapi
db = dbapi.connect(".pytv.dat")

Pero esto nos puede ocasionar un problema cuando la aplicación este instalada, por lo que una opción recomendable seria darle a las rutas de los archivos una ruta absoluta, como por ejemplo:

pixmap = QtGui.QPixmap('/usr/share/pytv/pytv.png')

Que es donde se copiarían en el caso de PyTv todos los archivos del programa segun especificamos al configurar el archivo DIRS y RULES en la carpeta DEBIAN en el punto anterior.
Otro detalle a tener en cuenta, como es en el caso de la Base de Datos que se crea en PyTv para ser usada con SQLite, es que todo lo que antes se creaba utilizando una ruta relativa en el directorio actual, ahora pasaria a crearse a partir del "home".

5) Creando el archivo ".desktop"
El archivo ".desktop" cumple la función de ser una especie de acceso directo. Se trata de un archivo de texto que contiene información de nuestro programa, define un icono y permite que el usuario lance el programa haciendo doble clic sobre el. El archivo "pytv.desktop" (el cual debe estar dentro de la carpeta "pytv-1.2" en el caso de este ejemplo) contiene lo siguiente:


[Desktop Entry]
Encoding=UTF-8
Name=PyTv
Icon=/usr/share/pytv/pytv.png
Comment=PyTv: Tv Series notification utility
Exec=/usr/bin/pytv
Terminal=false
Type=Application
Categories=GNOME;Utility;
StartupNotify=False

Como podemos ver es basicamente información descriptiva acerca de la aplicación, donde lo mas relevante serían las rutas de la imagén y ejecutable del programa.

6) Dentro de la carpeta "pytv-1.2" en la que seguimos trabajando, creamos el archivo pytv (en el caso de este ejemplo, obviamente "pytv" debería ser reemplazado por la aplicación con la que se esta trabajando), el cual contiene lo siguiente:

#!/bin/sh
python /usr/share/pytv/pytv.py

7) Momento de crear el Paquete DEB
Lo único que debemos hacer es situarnos en la carpeta "pytv-1.2" (reemplazar con el nombre de nuestra aplicación... si si, sigo insistiendo :P).

cd /home/deb/pytv-1.2

y luego ejecutar el comando:

sudo dpkg-buildpackage

Y ya deberíamos tener creado nuestro archivo ".deb" en la carpeta "deb".
En esta carpeta van a aparecer otros archivos mas junto con el ".deb" pero no son de importancia, así que pueden ser eliminados sin problema.
Y ahora podemos proceder a instalar la aplicación:





Advertencia: Al generar el Paquete DEB lo crea por la configuración del archivo CONTROL para la arquitectura especifica de la maquina en la que se esta trabajando. En mi caso "amd64", quizas haya otra forma que no se :P, pero para hacer un instalador "i386" lo que hice fue abrir la carpeta en una maquina virtual con otra arquitectura y correr el comando "sudo dpkg-buildpackage" dentro de la maquina virtual, y de paso probar en esa arquitectura si el instalador funcionaba correctamente.

Resultado final de los archivos de configuración y fuentes utilizados en el ejemplo: DESCARGAR

5 comments:

lavaramano said...

Un consejo, trata por lo general de no depender (tanto en Build-depends como en Depends) de revisiones de paquetes como "2.5.2-1ubuntu1", sino solamente en "2.5.2".
Aca tenes una explicacion del porque:
http://lintian.debian.org/tags/build-depends-on-1-revision.html
Aunque un ejemplo concreto, seria que yo que no uso ubuntu, jamas voy a poder resolver la dependencia de Python 2.5.2-ubuntu1 :-)


Tambien sobre la arquitectura. Esta puede ser 'all' u otra dependiendo de las...dependencias. Es decir, si estas empaquetando un modulo de Python que solamente utiliza codigo Python es 'all', pero si de repente tiene dependencia en una libreria de C y esta disponible para todas las archs pasaria a ser 'any' (ya que se puede compilar en todas las arquitecturas disponibles), sino nombras para las que se encuentra disponible (i386, amd64, powerpc, etc. Podes encontrar la lista completa ejecutando 'dpkg-architecture -L').

Otro comentario es que cuando ejecutes 'dpkg-buildpackage' lo hagas pasandole el parametro -r (con fakeroot como valor) por si en el armado debe ejecutar alguna parte como root.

Y para cerrar :-)
En las Build-dependencies te faltaria por lo menos: Python, justamente.
Y como consejo te diria que es conveniente armar paquetes utilizando algo como pbuilder que te crea un chroot vacio para que puedas jugar, instalar y romper a gusto sin modificar tu sistema; ademas de que si te llega a faltar alguna dependencia te salta de toque y te aseguras que funcione bien en todos lados.

Te dejo unos links con bastante info para sacarte todas las dudas:
http://www.debian.org/doc/packaging-manuals/python-policy/
http://www.debian.org/doc/debian-policy/
http://www.debian.org/doc/maint-guide

Saludos

Diego Sarmentero said...

Gracias por todas las recomendaciones :D!
Me voy a poner a leer!

Elias said...

Que BUEN POST!! MUY completo y detallado.
Espero poderlo probar pronto!

Exitos!

Juan said...

La verdad, muy buen trabajo, muy explcativo. El ejemplo adjuntado ayuda muchisimo tambien. Solamente tengo una consulta, cuando envio el comando "sudo dpkg-buildpackage" sobre el ejemplo que adjuntaste, me pone el siguiente error:
cp *.py /home/juan/Escritorio/pytv-1.2/debian/pytv/usr/share/pytv/
cp: no se puede efectuar «stat» sobre «*.py»: No existe el archivo o directorio
make: *** [install] Error 1
dpkg-buildpackage: error: debian/rules binary entregó error de estado de salida 2


O sea, parece como que nunca "descomprime" el .tar.gz para verificar que ahi adentro tiene los *.py

Ojo, tal vez estoy diciendo tremenda burrada porque es mi primer intento haciendo un paquete. Pero bueno, si tenes idea de porque puede ser, se agradece.

Saludos!!!

Diego Sarmentero said...

Tendría que ver exactamente como estas siguiendo los pasos. El path que pusiste para copiar los archivos ya de por si, se me hace medio sospechoso.