NetBSD s01e04 : Construire ses paquets pour pkgsrc

GNU/Linux Magazine n° 123 | janvier 2010 | Guillaume Lasmayous
Creative Commons
  • Actuellement 0 sur 5 étoiles
0
Merci d'avoir participé !
Vous avez déjà noté cette page, vous ne pouvez la noter qu'une fois !
Votre note a été changée, merci de votre participation !
Dans les épisodes précédents de cette série, vous avez, chers lecteurs, installé et configuré un draporange. Vous avez également découvert comment installer des logiciels, à partir des sources ou des packages binaires. Mais voilà. Aujourd'hui, vous avez trouvé LE logiciel, L'application que vous cherchiez depuis des années, et ELLE est enfin là. Hélas, personne n'a pensé à créer de pkgsrc convenable pour l'installer sans heurt sur notre système préféré. Dans cet article, j'illustrerai la création d'un package, pour proposer à la communauté NetBSD un nouveau logiciel.

1. Work In Progress ?

Le système de packages de NetBSD, pkgsrc, a été décrit en long, en large et en travers dans les épisodes précédents [2], je ne m'étendrai pas longuement dessus. C'est une structure arborescente de répertoires contenant les instructions amenant à l'installation de l'application de votre choix sur notre système. Pkgsrc est alimenté et maintenu par les développeurs officiels du projet.

Toutefois, pour faciliter la création de packages par tout un chacun (vous, moi), Thomas Klausner, aka wiz@, a lancé il y a quelques années pkgsrc-wip [1]. WIP, pour « Work In Progress », ou « En Chantier ». Le repository wip est hébergé chez Sourceforge, et n'importe quel utilisateur de NetBSD peut demander un commit bit sur le CVS pkgsrc-wip pour proposer de nouveaux packages.

WIP, ou -wip, ou encore pkgsrc-wip, est donc un repository « parallèle » au pkgsrc officiel. De nouvelles versions des applications présentes dans pkgsrc y sont intégrées afin d'être testées avant leur intégration dans le repository officiel (ça a été le cas de firefox3.5 par exemple, mais aussi de XFCE4.6), ou bien des versions « instables » (de développement), les versions stables étant dans pkgsrc.

Dans cet article, nous allons nous intéresser à un outil que je maintiens dans pkgsrc : wip/ccxstream (qui entre temps a été commité dans le repository officiel - Merci Thomas! - dans la catégorie multimédia).

2. Un environnement de travail au poil

Avant de commencer, il est indispensable de préparer son environnement de travail.

En ce qui concerne les outils, on sera bien inspiré d'installer le meta-pkg meta-pkgs/pkg_developer, qui installera tous les outils nécessaires à la création de paquets dans pkgsrc. De même, il est souhaitable de fixer la valeur de la variable PKG_DELVELOPER à YES dans le fichier /etc/mk.conf, afin d'effectuer des vérifications supplémentaires visant à assurer la qualité des paquets en cours de développement.

Le « meta-paquet » meta-pkgs/pkg_developer va, entre autres, installer pkgtools/pkglint. pkglint vérifie qu'un certain nombre de « best-practices » de création de pkgsrc sont respectées, afin d'éviter des erreurs triviales dans notre paquet (une PLIST ou une DESCR mal renseignée, par exemple).

Il est de plus (très) vivement recommandé de jeter un œil à la documentation de pkgsrc [3] pour comprendre dans les grandes lignes comment fonctionne le framework. Il sera toujours temps de s'y référer lorsqu'on sera confronté à un problème insurmontable.

En gros, faites ce que je dis, pas ce que j'ai fait…

Note

un meta-paquet est un paquet virtuel qui permettra d'installer plusieurs autres paquets (non virtuels, eux ;) )

3. wip/ccxstream

wip/ccxstream est une application que j'ai installée récemment sur mon serveur @home. Elle permet de streamer le contenu d'un répertoire depuis un serveur vers une XBox ou une machine faisant tourner XBox Media Center, via le protocole XBMSP.

3.1 Création de la structure

Pour la suite de cet article, je supposerai que votre arbre pkgsrc est à l'emplacement /usr/pkgsrc, et que wip est donc dans /usr/pkgsrc/wip. On se place donc dans l'arborescence /usr/pkgsrc/wip (on aura préalablement téléchargé l'archive la plus récente sur pkgsrc-wip [1] et on l'aura extraite à l'emplacement adéquat). On va créer un répertoire destiné à recevoir notre package :

guigui@zezette [/usr/pkgsrc/wip]

% sudo mkdir ccxstream

Pour créer la structure de base, on va utiliser un outil fourni dans pkgsrc, url2pkg (que l'on aura pris soin d'installer auparavant). Ce script prend en entrée l'URL d'un tarball à télécharger, et crée les fichiers de base nécessaires à pkgsrc pour fonctionner : Makefile, DESCR, distinfo et PLIST:

- Makefile comporte les instructions de configuration, compilation et installation du package que nous sommes en train de créer.

- DESCR contient la description détaillée du programme. Cette information sera reprise dans le pkg_summary, utilisée par pkgin.

- distinfo regroupe les informations de contrôle de l'authenticité de l'archive téléchargée : taille et sommes de contrôle SHA1 et RMD160.

- PLIST dresse la liste des fichiers installés par le programme.

On se référera à [2] pour de plus amples détails sur le rôle de ces fichiers.

A l'invocation de l'outil url2pkg :

sudo url2pkg http://garr.dl.sourceforge.net/project/xbplayer/XStream%20Servers/ccXStream%201.0.15%20for%20Linux/ccxstream-1.0.15.tar.gz

le Makefile est présenté, pour procéder à quelques premiers ajustements :

# $NetBSD$

#

DISTNAME=       ccxstream-1.0.15

CATEGORIES=     wip

MASTER_SITES=   http://garr.dl.sourceforge.net/project/xbplayer/XStream%20Servers/ccXStream%201.0.15%20for%20Linux/

MAINTAINER=     INSERT_YOUR_MAIL_ADDRESS_HERE

HOMEPAGE=       http://garr.dl.sourceforge.net/project/xbplayer/XStream%20Servers/ccXStream%201.0.15%20for%20Linux/

COMMENT=        TODO: Short description of the package

#LICENSE=       # TODO: (see mk/license.mk)

PKG_DESTDIR_SUPPORT=    user-destdir

# url2pkg-marker (please do not remove this line.)

.include "../../mk/bsd.pkg.mk"

- Le premier bloc précise le nom du package tel qu'il apparaîtra dans pkg_info (DISTNAME), la catégorie dans laquelle est classée l'application (CATEGORIES) - une application pouvant être listée dans plusieurs catégories - ainsi que le site sur lequel télécharger les sources (MASTER_SITES).

- Le deuxième bloc détaille l'adresse mail du mainteneur (MAINTAINER), la homepage de l'application (HOMEPAGE), ainsi qu'un court descriptif d'une ligne (COMMENT) et la licence du code (LICENSE).

La directive PKG_DESTDIR_SUPPORT précise que l'on supporte l'installation dans un répertoire utilisateur. Cette fonctionnalité sera complètement détaillée dans la suite de l'article.

Nous y reviendrons. Validons pour l'instant la création du fichier pour procéder au téléchargement de l'archive:

% sudo url2pkg http://garr.dl.sourceforge.net/project/xbplayer/XStream%20Servers/ccXStream%201.0.15%20for%20Linux/ccxstream-1.0.15.tar.gz

url2pkg> Running "make makesum" ...

=> Bootstrap dependency digest>=20010302: found digest-20080510

===> Skipping vulnerability checks.

WARNING: No /var/db/pkg/pkg-vulnerabilities file found.

WARNING: To fix run: `/usr/sbin/pkg_admin -K /var/db/pkg fetch-pkg-vulnerabilities'.

url2pkg> Running "make extract" ...

=> Bootstrap dependency digest>=20010302: found digest-20080510

===> Skipping vulnerability checks.

WARNING: No /var/db/pkg/pkg-vulnerabilities file found.

WARNING: To fix run: `/usr/sbin/pkg_admin -K /var/db/pkg fetch-pkg-vulnerabilities'.

=> Checksum SHA1 OK for ccxstream-1.0.15.tar.gz

=> Checksum RMD160 OK for ccxstream-1.0.15.tar.gz

===> Installing dependencies for ccxstream-1.0.15

===> Overriding tools for ccxstream-1.0.15

===> Extracting for ccxstream-1.0.15

url2pkg> Adjusting the Makefile.

Remember to correct CATEGORIES, HOMEPAGE, COMMENT, and DESCR when you're done!

Good luck! (See pkgsrc/doc/pkgsrc.txt for some more help :-)

Le fichier est téléchargé, puis la commande make makesum est exécutée pour calculer les sommes de contrôle de l'archive et renseigner le fichier distinfo.

Note

Dans mon cas, j'utilise sudo pour permettre le stockage du fichier dans /usr/pkgsrc/distfiles, étant donné que /usr/pkgsrc ne m'appartient pas.

Pour se simplifier la vie par la suite, on s'approprie le répertoire et les fichiers qu'il contient :

guigui@zezette [/usr/pkgsrc/wip]

% sudo chown guigui:guigui ccxstream

3.2 Première compilation

A la fin de l'exécution de url2pkg, les fichiers suivants ont été créés dans notre répertoire :

% ls

DESCR    Makefile PLIST    distinfo work

Le répertoire work, ou ${WRKDIR}, est le répertoire dans lequel les sources ont été extraites, et dans lequel aura lieu la compilation du paquet. Avant de lancer la compilation, on va procéder à la mise à jour du Makefile.

On remplace le contenu de la variable MAINTAINER par l'adresse mail qui servira à vous contacter pour toute question relative au pkgsrc, rapport de bug, … De même, on corrige l'URL vers le tarball des sources qui se trouve sur Sourceforge, afin utiliser la macro fournie par pkgsrc : ${MASTER_SITE_SOURCEFORGE:=xbplayer/}. Les variables MASTER_SITE_* sont définies dans le fichier ${PKGSRCDIR}/mk/fetch.mk.

Enfin, on met les champs CATEGORIES et le COMMENT à jour, avec une brève description du package.

# $NetBSD$

#

DISTNAME=       ccxstream-1.0.15

CATEGORIES=     multimedia net

MASTER_SITES=   ${MASTER_SITE_SOURCEFORGE:=xbplayer/}

MAINTAINER=     netbsd@guigui2.net

HOMEPAGE=       http://garr.dl.sourceforge.net/project/xbplayer/XStream%20Servers/ccXStream%201.0.15%20for%20Linux/

COMMENT=        Program for streaming multimedia content to XMBC over XBMSP protocol

#LICENSE=       # TODO: (see mk/license.mk)

PKG_DESTDIR_SUPPORT=    user-destdir

.include "../../mk/bsd.pkg.mk"

Le Makefile mis à jour, on lance une première compilation, « pour voir » :

% make

=> Bootstrap dependency digest>=20010302: found digest-20080510

===> Skipping vulnerability checks.

WARNING: No /var/db/pkg/pkg-vulnerabilities file found.

WARNING: To fix run: `/usr/sbin/pkg_admin -K /var/db/pkg fetch-pkg-vulnerabilities'.

=> Checksum SHA1 OK for ccxstream-1.0.15.tar.gz

=> Checksum RMD160 OK for ccxstream-1.0.15.tar.gz

===> Installing dependencies for ccxstream-1.0.15

===> Overriding tools for ccxstream-1.0.15

===> Extracting for ccxstream-1.0.15

===> Patching for ccxstream-1.0.15

===> Creating toolchain wrappers for ccxstream-1.0.15

===> Configuring for ccxstream-1.0.15

===> Building for ccxstream-1.0.15

--- ccxfile.o ---

--- ccutil.o ---

--- ccbuffer.o ---

--- ccdebug.o ---

--- ccxmltrans.o ---

--- ccxfile.o ---

cc -O2 -I. -g -c ccxfile.c

--- ccbuffer.o ---

cc -O2 -I. -g -c ccbuffer.c

--- ccutil.o ---

cc -O2 -I. -g -c ccutil.c

--- ccxmltrans.o ---

cc -O2 -I. -g -c ccxmltrans.c

--- ccdebug.o ---

cc -O2 -I. -g -c ccdebug.c

--- ccxencode.o ---

--- ccxstream.o ---

--- ccxclient.o ---

--- ccxclientconn.o ---

--- ccxdiscover.o ---

--- ccxencode.o ---

cc -O2 -I. -g -c ccxencode.c

--- ccxclient.o ---

cc -O2 -I. -g -c ccxclient.c

--- ccxclientconn.o ---

cc -O2 -I. -g -c ccxclientconn.c

--- ccxstream.o ---

cc -O2 -I. -g -c ccxstream.c

--- ccxdiscover.o ---

cc -O2 -I. -g -c ccxdiscover.c

--- ccxtest.o ---

cc -O2 -I. -g -c ccxtest.c

--- ccxtest ---

cc -O2 -I. -g -Wl,-R/usr/pkg/lib -lreadline -ltermcap -o ccxtest ccxtest.c

--- ccxstream ---

cc -O2 -I. -g -Wl,-R/usr/pkg/lib -lreadline -ltermcap -o ccxstream ccxstream.c

--- ccxtest ---

ld: cannot find -lreadline

*** [ccxtest] Error code 1

--- ccxstream ---

ld: cannot find -lreadline

*** [ccxstream] Error code 1

2 errors

make: stopped in /usr/pkgsrc/wip/ccxstream/work/ccxstream-1.0.15

*** Error code 2

Stop.

make: stopped in /usr/pkgsrc/wip/ccxstream

*** Error code 1

Stop.

make: stopped in /usr/pkgsrc/wip/ccxstream

Deux erreurs sont signalées. Le linker ld ne trouve pas la bibliothèque readline. Il faut préciser dans le Makefile que la bibliothèque readline est une dépendance de notre package. Pour cela, on va utiliser le mécanisme des buildlink de pkgsrc.

3.3 buildlink3

Décriés pour leur lenteur, adulés pour leur puissance, les fichiers buildlink3.mk sont un mécanisme de pkgsrc qui permettent de gérer proprement les problèmes de dépendance, mais également les probables soucis de localisation d'includes et bibliothèques que posent souvent les programmes liés à des bibliothèques dynamiques [4]. Dans le cas de wip/ccxstream, on va ajouter le bl3 de readline dans le Makefile, de la façon suivante :

# $NetBSD$

#

DISTNAME=       ccxstream-1.0.15

CATEGORIES=     multimedia net

MASTER_SITES=   ${MASTER_SITE_SOURCEFORGE:=xbplayer/}

MAINTAINER=     netbsd@guigui2.net

HOMEPAGE=       http://garr.dl.sourceforge.net/project/xbplayer/XStream%20Servers/ccXStream%201.0.15%20for%20Linux/

COMMENT=        Program for streaming multimedia content to XMBC over XBMSP protocol

#LICENSE=       # TODO: (see mk/license.mk)

PKG_DESTDIR_SUPPORT=    user-destdir

.include "../../devel/readline/buildlink3.mk"

.include "../../mk/bsd.pkg.mk"

Puis on reteste la compilation.

% make clean && make

===> Cleaning for ccxstream-1.0.15

=> Bootstrap dependency digest>=20010302: found digest-20080510

===> Skipping vulnerability checks.

WARNING: No /var/db/pkg/pkg-vulnerabilities file found.

WARNING: To fix run: `/usr/sbin/pkg_admin -K /var/db/pkg fetch-pkg-vulnerabilities'.

=> Checksum SHA1 OK for ccxstream-1.0.15.tar.gz

=> Checksum RMD160 OK for ccxstream-1.0.15.tar.gz

===> Installing dependencies for ccxstream-1.0.15

===> Overriding tools for ccxstream-1.0.15

===> Extracting for ccxstream-1.0.15

===> Patching for ccxstream-1.0.15

===> Creating toolchain wrappers for ccxstream-1.0.15

===> Configuring for ccxstream-1.0.15

===> Building for ccxstream-1.0.15

--- ccxfile.o ---

--- ccutil.o ---

--- ccbuffer.o ---

--- ccdebug.o ---

--- ccxmltrans.o ---

--- ccxfile.o ---

cc -O2 -I/usr/include -I. -g -I/usr/include -c ccxfile.c

--- ccutil.o ---

cc -O2 -I/usr/include -I. -g -I/usr/include -c ccutil.c

--- ccbuffer.o ---

cc -O2 -I/usr/include -I. -g -I/usr/include -c ccbuffer.c

--- ccdebug.o ---

cc -O2 -I/usr/include -I. -g -I/usr/include -c ccdebug.c

--- ccxmltrans.o ---

cc -O2 -I/usr/include -I. -g -I/usr/include -c ccxmltrans.c

--- ccxencode.o ---

--- ccxstream.o ---

--- ccxclient.o ---

--- ccxencode.o ---

cc -O2 -I/usr/include -I. -g -I/usr/include -c ccxencode.c

--- ccxstream.o ---

cc -O2 -I/usr/include -I. -g -I/usr/include -c ccxstream.c

--- ccxclient.o ---

cc -O2 -I/usr/include -I. -g -I/usr/include -c ccxclient.c

--- ccxclientconn.o ---

cc -O2 -I/usr/include -I. -g -I/usr/include -c ccxclientconn.c

--- ccxdiscover.o ---

cc -O2 -I/usr/include -I. -g -I/usr/include -c ccxdiscover.c

--- ccxtest.o ---

cc -O2 -I/usr/include -I. -g -I/usr/include -c ccxtest.c

--- ccxtest ---

cc -O2 -I/usr/include -I. -g -I/usr/include -L/usr/lib -Wl,-R/usr/lib -Wl,-R/usr/pkg/lib -lreadline -ltermcap -o ccxtest ccxtest.c

--- ccxstream ---

cc -O2 -I/usr/include -I. -g -I/usr/include -L/usr/lib -Wl,-R/usr/lib -Wl,-R/usr/pkg/lib -lreadline -ltermcap -o ccxstream ccxstream.c

--- ccxtest ---

/var/tmp//cc4d3504.o: In function `discovery_cb':

/usr/pkgsrc/wip/ccxstream/work/ccxstream-1.0.15/ccxtest.c:358: undefined reference to `cc_xstrdup'

/var/tmp//cc4d3504.o: In function `fuzzy_get_file':

/usr/pkgsrc/wip/ccxstream/work/ccxstream-1.0.15/ccxtest.c:290: undefined reference to `cc_xstream_client_file_open'

/usr/pkgsrc/wip/ccxstream/work/ccxstream-1.0.15/ccxtest.c:297: undefined reference to `cc_xstream_client_file_read'

/usr/pkgsrc/wip/ccxstream/work/ccxstream-1.0.15/ccxtest.c:321: undefined reference to `cc_xstream_client_file_backwards'

/usr/pkgsrc/wip/ccxstream/work/ccxstream-1.0.15/ccxtest.c:335: undefined reference to `cc_xstream_client_close'

/usr/pkgsrc/wip/ccxstream/work/ccxstream-1.0.15/ccxtest.c:309: undefined reference to `cc_xfree'

/var/tmp//cc4d3504.o: In function `get_file':

/usr/pkgsrc/wip/ccxstream/work/ccxstream-1.0.15/ccxtest.c:186: undefined reference to `cc_xstream_client_file_open'

[...]

/usr/pkgsrc/wip/ccxstream/work/ccxstream-1.0.15/ccxstream.c:1984: undefined reference to `cc_xcalloc'

/usr/pkgsrc/wip/ccxstream/work/ccxstream-1.0.15/ccxstream.c:1986: undefined reference to `cc_xmemdup'

/var/tmp//ccAD30QE.o: In function `cc_xstream_connection_free':

/usr/pkgsrc/wip/ccxstream/work/ccxstream-1.0.15/ccxstream.c:460: undefined reference to `cc_xfree'

/var/tmp//ccAD30QE.o: In function `cc_xstream_path_relative_to_absolute':

/usr/pkgsrc/wip/ccxstream/work/ccxstream-1.0.15/ccxstream.c:250: undefined reference to `cc_xstrdup'

*** [ccxstream] Error code 1

2 errors

make: stopped in /usr/pkgsrc/wip/ccxstream/work/ccxstream-1.0.15

*** Error code 2

Stop.

make: stopped in /usr/pkgsrc/wip/ccxstream

*** Error code 1

Stop.

make: stopped in /usr/pkgsrc/wip/ccxstream

guigui@zezette [/usr/pkgsrc/wip/ccxstream]

Beuhhhhhh ; ça juste marche pas ©…

En fait, comme bien souvent pour des programmes développés sous Linux, il faut utiliser GNU Make en lieu et place de BSD Make pour la compilation du programme. L'utilisation de GNU Make (gmake sous NetBSD) se fait en introduisant la directive USE_TOOLS+= gmake dans le Makefile:

# $NetBSD$

#

DISTNAME=       ccxstream-1.0.15

CATEGORIES=     multimedia net

MASTER_SITES=   ${MASTER_SITE_SOURCEFORGE:=xbplayer/}

MAINTAINER=     netbsd@guigui2.net

HOMEPAGE=       http://garr.dl.sourceforge.net/project/xbplayer/XStream%20Servers/ccXStream%201.0.15%20for%20Linux/

COMMENT=        Program for streaming multimedia content to XMBC over XBMSP protocol

#LICENSE=       # TODO: (see mk/license.mk)

PKG_DESTDIR_SUPPORT=    user-destdir

USE_TOOLS+=     gmake

.include "../../devel/readline/buildlink3.mk"

.include "../../mk/bsd.pkg.mk"

Cette fois-ci devrait être la bonne.

% make clean && make

===> Cleaning for ccxstream-1.0.15

=> Bootstrap dependency digest>=20010302: found digest-20080510

===> Skipping vulnerability checks.

WARNING: No /var/db/pkg/pkg-vulnerabilities file found.

WARNING: To fix run: `/usr/sbin/pkg_admin -K /var/db/pkg fetch-pkg-vulnerabilities'.

=> Checksum SHA1 OK for ccxstream-1.0.15.tar.gz

=> Checksum RMD160 OK for ccxstream-1.0.15.tar.gz

===> Installing dependencies for ccxstream-1.0.15

=> Build dependency gmake>=3.81: found gmake-3.81

===> Overriding tools for ccxstream-1.0.15

===> Extracting for ccxstream-1.0.15

===> Patching for ccxstream-1.0.15

===> Creating toolchain wrappers for ccxstream-1.0.15

===> Configuring for ccxstream-1.0.15

===> Building for ccxstream-1.0.15

cc -O2 -I/usr/include -I. -g -I/usr/include -c -o ccxstream.o ccxstream.c

cc -O2 -I/usr/include -I. -g -I/usr/include -c -o ccxfile.o ccxfile.c

cc -O2 -I/usr/include -I. -g -I/usr/include -c -o ccutil.o ccutil.c

cc -O2 -I/usr/include -I. -g -I/usr/include -c -o ccbuffer.o ccbuffer.c

cc -O2 -I/usr/include -I. -g -I/usr/include -c -o ccdebug.o ccdebug.c

cc -O2 -I/usr/include -I. -g -I/usr/include -c -o ccxmltrans.o ccxmltrans.c

cc -O2 -I/usr/include -I. -g -I/usr/include -c -o ccxencode.o ccxencode.c

cc -O2 -I/usr/include -I. -g -I/usr/include -c -o ccxtest.o ccxtest.c

cc -O2 -I/usr/include -I. -g -I/usr/include -c -o ccxclient.o ccxclient.c

cc -O2 -I/usr/include -I. -g -I/usr/include -c -o ccxclientconn.o ccxclientconn.c

cc -O2 -I/usr/include -I. -g -I/usr/include -c -o ccxdiscover.o ccxdiscover.c

cc -L/usr/lib -Wl,-R/usr/lib -Wl,-R/usr/pkg/lib -lreadline -ltermcap ccxtest.o ccxclient.o ccxclientconn.o ccutil.o ccbuffer.o ccdebug.o ccxmltrans.o ccxencode.o ccxdiscover.o   -o ccxtest

cc -L/usr/lib -Wl,-R/usr/lib -Wl,-R/usr/pkg/lib -lreadline -ltermcap ccxstream.o ccxfile.o ccutil.o ccbuffer.o ccdebug.o ccxmltrans.o ccxencode.o   -o ccxstream

=> Unwrapping files-to-be-installed.

guigui@zezette [/usr/pkgsrc/wip/ccxstream]

3.4 On installe

Maintenant qu'il n'y a plus d'erreurs de compilation, on va passer à la phase d'installation. Mais idéalement, sans interférence avec notre système installé. La variable USE_DESTDIR vient à notre secours à cette étape.

3.4.1 Destdir support

Joerg Sonnenberger a fait un énorme boulot dans pkgsrc, en simplifiant, rationalisant l'infrastructure de création des paquets, … Entre autres choses, il a introduit le destdir-support, qui permet de préciser à pkgsrc que l'on veut créer un paquet en tant que simple utilisateur. Les opérations d'installation se feront alors dans un sous-répertoire .destdir du répertoire work du pkgsrc. Ceci va notamment permettre de simplifier la génération des PLISTs, fichiers contenant la liste des fichiers créés lors de l'installation d'un logiciel par pkgsrc.

Premier essai :

guigui@zezette [/usr/pkgsrc/wip/ccxstream]

% make USE_DESTDIR=yes install

=> Bootstrap dependency digest>=20010302: found digest-20080510

===> Skipping vulnerability checks.

WARNING: No /var/db/pkg/pkg-vulnerabilities file found.

WARNING: To fix run: `/usr/sbin/pkg_admin -K /var/db/pkg fetch-pkg-vulnerabilities'.

===> Installing for ccxstream-1.0.15

gmake: *** Pas de règle pour fabriquer la cible « install ». Arrêt.

*** Error code 2

Stop.

make: stopped in /usr/pkgsrc/wip/ccxstream

*** Error code 1

Stop.

make: stopped in /usr/pkgsrc/wip/ccxstream

Damn ! Le Makefile ne comporte pas de cible install.

3.4.2 do-install

Qu'à cela ne tienne. Pkgsrc a prévu cette éventualité. Nous allons donc écrire une procédure d'installation personnalisée. Pour ce faire, on va renseigner la section do-install du Makefile de notre logiciel.

Les fichiers à installer sont les binaires ccxtest et ccxstream, ainsi que les fichiers de documentation COPYRIGHT, ChangeLog, PORTING, README, TODO, xbmsp.txt, xbmsp-xml.txt et xbmsp-rc. Le Makefile ressemble donc maintenant à ça :

# $NetBSD$

#

DISTNAME=       ccxstream-1.0.15

CATEGORIES=     multimedia net

MASTER_SITES=   ${MASTER_SITE_SOURCEFORGE:=xbplayer/}

MAINTAINER=     netbsd@guigui2.net

HOMEPAGE=       http://garr.dl.sourceforge.net/project/xbplayer/XStream%20Servers/ccXStream%201.0.15%20for%20Linux/

COMMENT=        Program for streaming multimedia content to XMBC over XBMSP protocol

#LICENSE=       # TODO: (see mk/license.mk)

PKG_DESTDIR_SUPPORT=    user-destdir

USE_TOOLS+=     gmake

DOCDIR=                 share/doc/ccxstream

INSTALLATION_DIRS=      bin ${DOCDIR}

do-install:

        ${INSTALL_PROGRAM} ${WRKSRC}/ccxstream ${DESTDIR}${PREFIX}/bin

        ${INSTALL_PROGRAM} ${WRKSRC}/ccxtest ${DESTDIR}${PREFIX}/bin

        ${INSTALL_DATA} ${WRKSRC}/*.txt ${DESTDIR}${PREFIX}/${DOCDIR}

        ${INSTALL_DATA} ${WRKSRC}/xbmsp-rc ${DESTDIR}${PREFIX}/${DOCDIR}

        ${INSTALL_DATA} ${WRKSRC}/COPYRIGHT ${DESTDIR}${PREFIX}/${DOCDIR}

        ${INSTALL_DATA} ${WRKSRC}/ChangeLog ${DESTDIR}${PREFIX}/${DOCDIR}

        ${INSTALL_DATA} ${WRKSRC}/README ${DESTDIR}${PREFIX}/${DOCDIR}

        ${INSTALL_DATA} ${WRKSRC}/PORTING ${DESTDIR}${PREFIX}/${DOCDIR}

        ${INSTALL_DATA} ${WRKSRC}/TODO ${DESTDIR}${PREFIX}/${DOCDIR}

.include "../../devel/readline/buildlink3.mk"

.include "../../mk/bsd.pkg.mk"

Dans la section do-install, on précise quels sont les programmes à installer, au moyen de la macro ${INSTALL_PROGRAM} qui se chargera d'appeler le programme install avec les bonnes options. On installe le programme ${WRKSRC}/ccxstream dans ${DESTDIR}${PREFIX}/bin. On précise ensuite quels autres fichiers (données, documentations, configuration) installer, au moyen de la macro ${INSTALL_DATA}. Ainsi, au moment de l'installation, si la variable USE_DESTDIR=yes est positionnée, alors ${DESTDIR} prendra la valeur ${WORKDIR}/.destdir. Si la variable n'est pas positionnée, alors on installera directement dans ${PREFIX}.

pkgsrc se charge de créer automatiquement les répertoires d'installation. Si ceux-ci n'existent pas encore dans notre système, il faut auparavant prendre soin de les ajouter dans la directive INSTALLATION_DIRS. Sinon, l'installation échouera avec un message du style :

/usr/bin/install -c -s -o guigui -g guigui -m 755 /usr/pkgsrc/wip/ccxstream/work/ccxstream-1.0.15/ccxstream /usr/pkgsrc/wip/ccxstream/work/.destdir/usr/pkg/bin/

install: /usr/pkgsrc/wip/ccxstream/work/.destdir/usr/pkg/bin/: open: No such file or directory

3.4.3 PLIST

Le destdir-support a deux intérêts majeurs à mes yeux :

- s'assurer que les fichiers ont été installés à la bonne place dans l'arborescence ;

- simplifier la création des PLISTs. En effet, lorsqu'on fait des tests de packaging, il n'est pas rare que l'on oublie des fichiers dans la PLIST, ce qui aura pour effet de les installer ou de les désinstaller incorrectement. Pour créer la PLIST, on va utiliser la cible make install avec l'option USE_DESTDIR=yes, vérifier les répertoires d'installation des paquets, puis utiliser la cible make print-PLIST, comme suit :

% make USE_DESTDIR=yes install

=> Bootstrap dependency digest>=20010302: found digest-20080510

===> Skipping vulnerability checks.

WARNING: No /var/db/pkg/pkg-vulnerabilities file found.

WARNING: To fix run: `/usr/sbin/pkg_admin -K /var/db/pkg fetch-pkg-vulnerabilities'.

=> Checksum SHA1 OK for ccxstream-1.0.15.tar.gz

=> Checksum RMD160 OK for ccxstream-1.0.15.tar.gz

===> Installing dependencies for ccxstream-1.0.15

=> Build dependency gmake>=3.81: found gmake-3.81

===> Overriding tools for ccxstream-1.0.15

===> Extracting for ccxstream-1.0.15

===> Patching for ccxstream-1.0.15

===> Creating toolchain wrappers for ccxstream-1.0.15

===> Configuring for ccxstream-1.0.15

===> Building for ccxstream-1.0.15

cc -O2 -I/usr/include -I. -g -I/usr/include -c -o ccxstream.o ccxstream.c

cc -O2 -I/usr/include -I. -g -I/usr/include -c -o ccxfile.o ccxfile.c

cc -O2 -I/usr/include -I. -g -I/usr/include -c -o ccutil.o ccutil.c

cc -O2 -I/usr/include -I. -g -I/usr/include -c -o ccbuffer.o ccbuffer.c

cc -O2 -I/usr/include -I. -g -I/usr/include -c -o ccdebug.o ccdebug.c

cc -O2 -I/usr/include -I. -g -I/usr/include -c -o ccxmltrans.o ccxmltrans.c

cc -O2 -I/usr/include -I. -g -I/usr/include -c -o ccxencode.o ccxencode.c

cc -O2 -I/usr/include -I. -g -I/usr/include -c -o ccxtest.o ccxtest.c

cc -O2 -I/usr/include -I. -g -I/usr/include -c -o ccxclient.o ccxclient.c

cc -O2 -I/usr/include -I. -g -I/usr/include -c -o ccxclientconn.o ccxclientconn.c

cc -O2 -I/usr/include -I. -g -I/usr/include -c -o ccxdiscover.o ccxdiscover.c

cc -L/usr/lib -Wl,-R/usr/lib -Wl,-R/usr/pkg/lib -lreadline -ltermcap ccxtest.o ccxclient.o ccxclientconn.o ccutil.o ccbuffer.o ccdebug.o ccxmltrans.o ccxencode.o ccxdiscover.o   -o ccxtest

cc -L/usr/lib -Wl,-R/usr/lib -Wl,-R/usr/pkg/lib -lreadline -ltermcap ccxstream.o ccxfile.o ccutil.o ccbuffer.o ccdebug.o ccxmltrans.o ccxencode.o   -o ccxstream

=> Unwrapping files-to-be-installed.

=> Creating /usr/pkgsrc/wip/ccxstream/work/ccxstream

===> Installing for ccxstream-1.0.15

=> Creating installation directories

/usr/bin/install -c -s -o root -g wheel -m 755 /usr/pkgsrc/wip/ccxstream/work/ccxstream-1.0.15/ccxstream /usr/pkgsrc/wip/ccxstream/work/.destdir/usr/pkg/bin/

/usr/bin/install -c -s -o root -g wheel -m 755 /usr/pkgsrc/wip/ccxstream/work/ccxstream-1.0.15/ccxtest /usr/pkgsrc/wip/ccxstream/work/.destdir/usr/pkg/bin/

/usr/bin/install -c -o root -g wheel -m 644 /usr/pkgsrc/wip/ccxstream/work/ccxstream-1.0.15/*.txt /usr/pkgsrc/wip/ccxstream/work/.destdir/usr/pkg/share/doc/ccxstream

/usr/bin/install -c -o root -g wheel -m 644 /usr/pkgsrc/wip/ccxstream/work/ccxstream-1.0.15/xbmsp-rc /usr/pkgsrc/wip/ccxstream/work/.destdir/usr/pkg/share/doc/ccxstream

/usr/bin/install -c -o root -g wheel -m 644 /usr/pkgsrc/wip/ccxstream/work/ccxstream-1.0.15/COPYRIGHT /usr/pkgsrc/wip/ccxstream/work/.destdir/usr/pkg/share/doc/ccxstream

/usr/bin/install -c -o root -g wheel -m 644 /usr/pkgsrc/wip/ccxstream/work/ccxstream-1.0.15/ChangeLog /usr/pkgsrc/wip/ccxstream/work/.destdir/usr/pkg/share/doc/ccxstream

/usr/bin/install -c -o root -g wheel -m 644 /usr/pkgsrc/wip/ccxstream/work/ccxstream-1.0.15/README /usr/pkgsrc/wip/ccxstream/work/.destdir/usr/pkg/share/doc/ccxstream

/usr/bin/install -c -o root -g wheel -m 644 /usr/pkgsrc/wip/ccxstream/work/ccxstream-1.0.15/PORTING /usr/pkgsrc/wip/ccxstream/work/.destdir/usr/pkg/share/doc/ccxstream

/usr/bin/install -c -o root -g wheel -m 644 /usr/pkgsrc/wip/ccxstream/work/ccxstream-1.0.15/TODO /usr/pkgsrc/wip/ccxstream/work/.destdir/usr/pkg/share/doc/ccxstream

=> Automatic manual page handling

guigui@zezette [/usr/pkgsrc/wip/ccxstream]

% find work/.destdir

work/.destdir

work/.destdir/usr

work/.destdir/usr/pkg

work/.destdir/usr/pkg/bin

work/.destdir/usr/pkg/bin/ccxstream

work/.destdir/usr/pkg/bin/ccxtest

work/.destdir/usr/pkg/share

work/.destdir/usr/pkg/share/doc

work/.destdir/usr/pkg/share/doc/ccxstream

work/.destdir/usr/pkg/share/doc/ccxstream/xbmsp-xml.txt

work/.destdir/usr/pkg/share/doc/ccxstream/xbmsp.txt

work/.destdir/usr/pkg/share/doc/ccxstream/xbmsp-rc

work/.destdir/usr/pkg/share/doc/ccxstream/COPYRIGHT

work/.destdir/usr/pkg/share/doc/ccxstream/ChangeLog

work/.destdir/usr/pkg/share/doc/ccxstream/README

work/.destdir/usr/pkg/share/doc/ccxstream/PORTING

work/.destdir/usr/pkg/share/doc/ccxstream/TODO

work/.destdir/usr/pkg/share/examples

work/.destdir/usr/pkg/share/examples/rc.d

work/.destdir/usr/pkg/share/examples/rc.d/ccxstream

Tout est sous contrôle, on peut donc créer la PLIST :

% sudo make USE_DESTDIR=yes print-PLIST > PLIST

@comment $NetBSD$

bin/ccxstream

bin/ccxtest

share/doc/ccxstream/COPYRIGHT

share/doc/ccxstream/ChangeLog

share/doc/ccxstream/PORTING

share/doc/ccxstream/README

share/doc/ccxstream/TODO

share/doc/ccxstream/xbmsp-rc

share/doc/ccxstream/xbmsp-xml.txt

share/doc/ccxstream/xbmsp.txt

share/examples/rc.d/ccxstream

Et voilà !

3.4.4 Fignolage

Nous y sommes presque. Quelques détails restent à régler. La HOMEPAGE doit pointer vers autre chose que le site de téléchargement. Ici, on la fait pointer vers le projet « père » de ccxstream, XBox Media Center, à l'adresse http://www.xbmc.org. Dans l'idéal, il faut également préciser la licence sous laquelle le code est publié. La liste des licences valides pour pkgsrc se trouve dans ${PKGSRCDIR}/licenses.

Comme ccxstream est un démon, nous allons également fournir un fichier de démarrage, que nous stockerons dans le sous-répertoire files de notre package. Ici, ccxstream.sh, puisque c'est ainsi qu'il s'appelle, contient le code suivant :

% cat files/ccxstream.sh

#!@RCD_SCRIPTS_SHELL@

#

# $NetBSD: ccxstream.sh $

#

# PROVIDE: ccxstream

# REQUIRE: DAEMON network

# KEYWORD: shutdown

. /etc/rc.subr

name="ccxstream"

rcvar=$name

command="@PREFIX@/bin/ccxstream"

command_args="-r - -f"

if [ -f /etc/rc.subr ]; then

        load_rc_config $name

        run_rc_command "$1"

else

        echo -n "${name}"

        ${command} ${ccxstream_flags} ${command_args}

fi

On précise dans ce fichier les arguments à utiliser pour le lancement du démon. Il faut également indiquer dans le Makefile que nous souhaitons installer ce fichier en tant que script de démarrage, au moyen de la directive :

RCD_SCRIPT= ccxstream

du Makefile.

J'ai également inclus un fichier MESSAGE, contenant des inscriptions qui seront affichées une fois l'installation du paquet dans notre système. Ce fichier contient les informations suivantes :

======================================================

Don't forget to update mountpoints (-S statements in

ccxstream_flags) before starting ccxstream.

======================================================

L'ultime vérification est faite avec l'outil lint (${PKGSRCDIR}/pkgtools/lintpkgsrc) qui va vérifier la validité de notre package - et que l'on a installé avant de commencer notre travail de packaging :

% pkglint

NOTE: Makefile:9: For consistency, please add a trailing slash to "http://www.xbmc.org".

WARN: MESSAGE:1: Expected a line of exactly 75 "=" characters.

ERROR: MESSAGE:2: "$NetBSD$" expected.

NOTE: MESSAGE:3: Trailing white-space.

NOTE: MESSAGE:4: Trailing white-space.

1 errors and 1 warnings found.

Il ne nous reste donc plus qu'à corriger les erreurs et warnings rapportés par pkglint pour avoir un package prêt à committer dans -wip.

3.4.5 rc.conf

Une fois le package propre, il reste un dernier point à tester : que le script de démarrage fonctionne proprement. Sur notre système de test, on installe donc wip/ccxstream, on copie le script de démarrage dans /etc/rc.d, comme le message suivant l'installation nous l'indique, puis on ajoute ceci dans notre /etc/rc.conf :

ccxstream=yes

ccxstream_flags="-S music=/stuff"

Un reboot plus tard, on s'assure que le process est bien lancé :

% ps aux |grep ccxstream

root    486 0,0 0,0   6580    732 ttyE0- S       5:57 0:00.00 /usr/pkg/bin/ccxstream -S music=/stuff -r - -f

Parfait.

Au final, le Makefile ressemble à ceci :

% cat /usr/pkgsrc/multimedia/ccxstream/Makefile

# $NetBSD: Makefile,v 1.1.1.1 2009/11/27 08:38:49 wiz Exp $

#

DISTNAME=       ccxstream-1.0.15

CATEGORIES=     audio multimedia net

MASTER_SITES=   ${MASTER_SITE_SOURCEFORGE:=xbplayer/}

MAINTAINER=     netbsd@guigui2.net

HOMEPAGE=       http://www.xbmc.org/

COMMENT=        Program for streaming multimedia content to XMBC over XBMSP protocol

#LICENSE=       # TODO: (see mk/license.mk)

PKG_DESTDIR_SUPPORT=    user-destdir

RCD_SCRIPTS=            ccxstream

USE_TOOLS+=             gmake

DOCDIR=                 share/doc/ccxstream

INSTALLATION_DIRS=      bin ${DOCDIR}

do-install:

        ${INSTALL_PROGRAM} ${WRKSRC}/ccxstream ${DESTDIR}${PREFIX}/bin/

        ${INSTALL_PROGRAM} ${WRKSRC}/ccxtest ${DESTDIR}${PREFIX}/bin/

        ${INSTALL_DATA} ${WRKSRC}/*.txt ${DESTDIR}${PREFIX}/${DOCDIR}

        ${INSTALL_DATA} ${WRKSRC}/xbmsp-rc ${DESTDIR}${PREFIX}/${DOCDIR}

        ${INSTALL_DATA} ${WRKSRC}/COPYRIGHT ${DESTDIR}${PREFIX}/${DOCDIR}

        ${INSTALL_DATA} ${WRKSRC}/ChangeLog ${DESTDIR}${PREFIX}/${DOCDIR}

        ${INSTALL_DATA} ${WRKSRC}/README ${DESTDIR}${PREFIX}/${DOCDIR}

        ${INSTALL_DATA} ${WRKSRC}/PORTING ${DESTDIR}${PREFIX}/${DOCDIR}

        ${INSTALL_DATA} ${WRKSRC}/TODO ${DESTDIR}${PREFIX}/${DOCDIR}

.include "../../devel/readline/buildlink3.mk"

.include "../../mk/bsd.pkg.mk"

3.5 On committe

Tout est prêt, on peut enfin mettre le package à disposition de tout le monde pour de plus amples tests. Pour ce faire, on va committer dans le repository wip, sur Sourceforge. Il va de soi que vous devrez au préalable disposer d'un compte sur ce site, et avoir été autorisé par wiz@ à accéder au repository en écriture. Le script import-package.sh est présent dans le dépôt pkgsrc-wip pour nous simplifier le travail d'import d'un nouveau paquet. Il suffit de l'invoquer depuis le répertoire de notre paquet, puis de vérifier si le message de commit est correct, avant de valider :

../import-package.sh

[18:33]

Please wait while determining PKGNAME and DESCR_SRC.

Edited message follows:

----------------------------------------------------------------------

Import ccxstream-1.0.15 as wip/ccxstream.

Program for streaming multimedia content to XBox Media Center over XBMSP

protocol.

----------------------------------------------------------------------

CVSROOT:        :ext:guigui2@pkgsrc-wip.cvs.sourceforge.net:/cvsroot/pkgsrc-wip

ROOTDIR:        

PKGPATH:        wip/ccxstream

TAGS:           GUIGUI2 GUIGUI2_20091126

y, enter to import, ctrl-c to abort> y

guigui2@pkgsrc-wip.cvs.sourceforge.net's password:

N wip/ccxstream/distinfo

N wip/ccxstream/Makefile

N wip/ccxstream/MESSAGE

N wip/ccxstream/PLIST

N wip/ccxstream/DESCR

cvs import: Importing /cvsroot/pkgsrc-wip/wip/ccxstream/files

N wip/ccxstream/files/ccxstream.sh

No conflicts created by this import

/cvsroot/pkgsrc-wip/CVSROOT/ciabot_cvs.pl: no files specified

----------------------------------------------------------------------

If the import went OK, move away the wip/ccxstream directory

and run "cvs update -dPA ccxstream" in wip to complete

the import. If you got conflict errors, just cvs add the

conflicting files and cvs commit them.

Don't forget to add the package to wip/Makefile and remove

it from the TODO list.

Puis, comme nous l'indique le message, on supprime le répertoire, et on récupère à nouveau, pour vérifier si tout s'est bien passé :

% sudo rm -rf ccxstream

% sudo cvs update -dPA ccxstream

guigui2@pkgsrc-wip.cvs.sourceforge.net's password:

cvs update: Updating ccxstream

U ccxstream/DESCR

U ccxstream/MESSAGE

U ccxstream/Makefile

U ccxstream/PLIST

U ccxstream/distinfo

cvs update: Updating ccxstream/files

U ccxstream/files/ccxstream.sh

Parfait, pas d'erreur. Il ne nous reste maintenant plus qu'à prévenir la liste pkgsrc-wip-discuss de l'arrivée d'un nouveau package à réviser. Ce que j'ai fait ici [5].

Epilogue

En guise de revue du package, j'ai eu droit à un transfert du repository -wip vers le repository officiel de pkgsrc. Thomas Klausner a corrigé quelques bêtises qui restaient dans mon paquet avant de le transférer dans le repository officiel. Comme il me l'écrit, « Well, after I had fixed the few problems I noted, it looked finished… :)  ».

Les erreurs en question (tests incorrects dans le fichier configure, en particulier) auraient facilement pu être évitées si je n'avais pas oublié de positionner la variable PKG_DEVELOPER=yes dans le fichier /etc/mk.conf de la machine que j'ai utilisée pour construire ce paquet.

Au travers de cet article, vous avez pu entrevoir les capacités du framework pkgsrc pour le packaging d'applications pour NetBSD. Il y a bien entendu de nombreux autres aspects à décrire, tels l'écriture de patches, l'utilisation d'autres outils de compilation - tels CMake ou JAM, par exemple - la prise en compte d'options pour la compilation, ... Mais tout ceci fera certainement l'objet d'un nouvel article dans la série.

A partir de maintenant, le logiciel ccxstream fait partie de pkgsrc, on peut le trouver ici [6].

[1] http://pkgsrc-wip.sourceforge.net

[2] Voir S01E03, « Gestion des paquets » par C. “zatmania” Charpentier.

[3] http://www.netbsd.org/docs/pkgsrc/

[4] http://www.netbsd.org/docs/pkgsrc/buildlink.html

[5] http://sourceforge.net/mailarchive/forum.php?thread_name=4B0EC661.9000106%40guigui2.net&forum_name=pkgsrc-wip-review

[6] http://pkgsrc.se/multimedia/ccxstream