pkgsrc (3/6)

Previous Next

Aujourd’hui, Imil commence par une petite introduction “prosélytisme” sur le monde du libre, et le rôle important des packageurs dans cet univers. C’est beau, c’est de la poésie pure … Et si vous ne l’avez pas vu, commencez donc par aller chercher la bonne parole à la source car tout cela est bien dit, et ça mérite d’être entendu. Foncez, moi je vous attends ici. :)

C’est fait ? génial ! Commençons donc par un petit flashback.

Petit résumé des épisodes précédents

Cet arc est orienté autour de la création de packages, et de l’outil pkgsrc qui est basé sur bmake.

Pour illustrer notre propos, nous avons décidé de réaliser un package pour l’application truefalse, alors en version 1.0. Nous avons alors utilisé “urk2pkg”, un outil permettant de passer directement d’une url à un template de package.

Comme nous l’avons évoqué plus haut, dans pkgsrc, bmake est à l’œuvre. La pièce maîtresse de notre package est donc un Makefile que nous avons rempli. Après cette première version, la version 1.1 de truefalse est alors sortie, nécessitant une mise à jour de ce travail.

Le Makefile que nous avions alors était le suivant :

# $NetBSD$

VERS=           v1.1
DISTNAME=       truefalse-${VERS}
PKGNAME=        ${DISTNAME:S,-v,-,}
CATEGORIES=     misc
MASTER_SITES=   https://gitlab.com/iMil/truefalse/-/archive/${VERS}/

MAINTAINER=     truefalse@rancune.org
HOMEPAGE=       https://gitlab.com/iMil/truefalse/-/archive/${VERS}/
COMMENT=        First attempt at making a package
LICENSE=        original-bsd

INSTALLATION_DIRS=      bin

do-install:
	${INSTALL_PROGRAM} ${WRKSRC}/${PROGNAME} ${DESTDIR}/${PREFIX}/bin/${PROGNAME}

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

Quelques petits rappels importants :

PKG_DEVELOPER=     yes

D’ailleurs, en parlant d’installation, je ne peux pas faire ce résumé sans vous rappeler la formidable cible :

bmake stage-install

Qui permet de “simuler” une installation du package dans le répertoire “work”. C’est une utilisation du chemin ${DESTDIR}/${PREFIX}.

Nous avons également vu, entre les versions V1.0 et V1.1, comment faire un patch avec les commandes pkgvi et mkpatches.

Sortie de truefalse 2.0 : Aïe aïe aïe Caramba !!!

Tout cela nous amène à une nouvelle version de truefalse, dans laquelle upstream a introduit des modifications qui sont loin de nous plaire. La première, c’est un passage à gmake (GNU make) au lieu de bmake. La seconde est l’introduction d’une dépendance à glib.h :

truefalse 2.0 :

#include <stdlib.h>
#include <glib.h>

int
main(int argc, char *argv[])
{
	if (argc < 2) {
		g_assert_true(argc < 2);

		return EXIT_SUCCESS;
	}

	g_assert_false(argc < 2);

	return EXIT_FAILURE;
}
CFLAGS=  $(shell pkg-config --cflags glib-2.0)
LDFLAGS= $(shell pkg-config --libs glib-2.0)

truefalse: truefalse.c
	$(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)

Bon, pas de panique.

On commence par modifier le numéro de version dans le Makefile de notre package, et nous tentons de télécharger la nouvelle version :

# $NetBSD$

VERS=           v2.0
DISTNAME=       truefalse-${VERS}
PKGNAME=        ${DISTNAME:S,-v,-,}
CATEGORIES=     misc
MASTER_SITES=   https://gitlab.com/iMil/truefalse/-/archive/${VERS}/

MAINTAINER=     truefalse@rancune.org
HOMEPAGE=       https://gitlab.com/iMil/truefalse/-/archive/${VERS}/
COMMENT=        First attempt at making a package
LICENSE=        original-bsd

INSTALLATION_DIRS=      bin

do-install:
	${INSTALL_PROGRAM} ${WRKSRC}/${PROGNAME} ${DESTDIR}/${PREFIX}/bin/${PROGNAME}

.include "../../mk/bsd.pkg.mk"
$ bmake distclean
===> Cleaning for truefalse-2.0
===> Dist cleaning for truefalse-2.0

$ bmake fetch
=> Bootstrap dependency digest>=20211023: found digest-20220214
=> Fetching truefalse-v2.0.tar.gz
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   571  100   571    0     0   1349      0 --:--:-- --:--:-- --:--:--  1636

Etant donné que les fichiers ont changé, ils nous faut également remettre à jour leur hash, localisé dans le fichier distinfo :

$ bmake makesum
=> Bootstrap dependency digest>=20211023: found digest-20220214

Voyons ce que cela donne si nous lançons naïvement une compilation :

$ bmake
=> Bootstrap dependency digest>=20211023: found digest-20220214
===> Checking for vulnerabilities in truefalse-2.0
===> Patching for truefalse-2.0
===> Creating toolchain wrappers for truefalse-2.0
===> Configuring for truefalse-2.0
===> Building for truefalse-2.0
bmake: don't know how to make all. Stop

bmake: stopped in /home/rancune/pkgsrc/wip/truefalse/work/truefalse-v2.0
*** Error code 2

Stop.
bmake[1]: stopped in /home/rancune/pkgsrc/wip/truefalse
*** Error code 1

Stop.
bmake: stopped in /home/rancune/pkgsrc/wip/truefalse

Sans grande surprise, cela échoue. Mais le message d’erreur est intéressant :

bmake: don't know how to make all. Stop

La raison de l’échec est le passage d’upstream de bmake à gmake, la version GNU de Make. On gère ceci en modifiant notre Makefile de façon à ce que ce soit bien gmake qui soit utilisé pour cette compilation grâce à la variable USE_TOOLS :

USE_TOOLS=      gmake 

On peut aussi constater qu’il n’y a pas de target “all” dans le Makefile du projet. Nous allons corriger ça avec la ligne :

BUILD_TARGET=   truefalse

Notre Makefile ressemble désormais à cela :

# $NetBSD$

VERS=           v2.0
DISTNAME=       truefalse-${VERS}
PKGNAME=        ${DISTNAME:S,-v,-,}
CATEGORIES=     misc
MASTER_SITES=   https://gitlab.com/iMil/truefalse/-/archive/${VERS}/

MAINTAINER=     truefalse@rancune.org
HOMEPAGE=       https://gitlab.com/iMil/truefalse/-/archive/${VERS}/
COMMENT=        First attempt at making a package
LICENSE=        original-bsd

INSTALLATION_DIRS=      bin

USE_TOOLS=      gmake
BUILD_TARGET=   truefalse

do-install:
	${INSTALL_PROGRAM} ${WRKSRC}/${PROGNAME} ${DESTDIR}/${PREFIX}/bin/${PROGNAME}

.include "../../mk/bsd.pkg.mk"
$ bmake
=> Bootstrap dependency digest>=20211023: found digest-20220214
===> Checking for vulnerabilities in truefalse-2.0
===> Building for truefalse-2.0
cc  truefalse.c -o truefalse
In file included from /usr/include/bits/libc-header-start.h:33,
                 from /usr/include/stdlib.h:25,
                 from truefalse.c:1:
/usr/include/features.h:412:4: warning: #warning _FORTIFY_SOURCE requires compiling 
with optimization (-O) [-Wcpp]
  412 | #  warning _FORTIFY_SOURCE requires compiling with optimization (-O)
      |    ^~~~~~~
truefalse.c:2:10: fatal error: glib.h: No such file or directory
    2 | #include <glib.h>
      |          ^~~~~~~~
compilation terminated.
*** Error code 1

Stop.
bmake: stopped in /home/rancune/pkgsrc/wip/truefalse/work/truefalse-v2.0
*** Error code 1

Stop.
bmake[1]: stopped in /home/rancune/pkgsrc/wip/truefalse
*** Error code 1

Stop.
bmake: stopped in /home/rancune/pkgsrc/wip/truefalse

Un nouveau message d’erreur : Nous avons avancé !!!!! \o/

Bien sûr, cela ne marche pas encore. Mais l’erreur est différente : ce n’est plus un problème de Makefile, mais un problème de C ! Le soft inclut désormais une dépendance à glib.h qu’il nous faut intégrer à notre package.

Tout cela semble bien compliqué, malheureusement nous sommes dans le process assez classique de portage d’un soft dont les auteurs n’ont pas fait trop attention aux autres plateformes. Heureusement, buildlink3 va nous aider.

Dans le repertoire du package de glib2 se trouve un fichier nommé buildlink3.mk. Si nous voulons compiler et linker notre projet avec glib2, il nous suffit d’include ce fichier dans notre Makefile à l’aide de la ligne suivante :

.include "../../devel/glib2/buildlink3.mk"

Nous pourrions agir de même pour toute dépendance nécessaire. Il faut avouer que cela nous simplifie drastiquement la vie !

Notre nouvelle version du Makefile est donc :

# $NetBSD$

VERS=           v2.0
DISTNAME=       truefalse-${VERS}
PKGNAME=        ${DISTNAME:S,-v,-,}
CATEGORIES=     misc
MASTER_SITES=   https://gitlab.com/iMil/truefalse/-/archive/${VERS}/

MAINTAINER=     truefalse@rancune.org
HOMEPAGE=       https://gitlab.com/iMil/truefalse/-/archive/${VERS}/
COMMENT=        First attempt at making a package
LICENSE=        original-bsd

INSTALLATION_DIRS=      bin

USE_TOOLS=      gmake
BUILD_TARGET=   truefalse

do-install:
	${INSTALL_PROGRAM} ${WRKSRC}/${PROGNAME} ${DESTDIR}/${PREFIX}/bin/${PROGNAME}

.include "../../devel/glib2/buildlink3.mk"
.include "../../mk/bsd.pkg.mk"

On peut maintenant recompiler tout ça : Ca marche !!!! \o/

$bmake clean
$bmake
$bmake deinstall
$bmake install

Passage a V2.1

Nouveau chapitre, nouvelle version de truefalse. Voici donc la version 2.1 !

Peu de changements cette fois-ci, sinon un ajout d’une cible d’installation dans le Makefile :

PROGNAME= truefalse 
BASE= /usr/local 

CFLAGS=  $(shell pkg-config --cflags glib-2.0) 
LDFLAGS= $(shell pkg-config --libs glib-2.0) 

$(PROGNAME): $(PROGNAME).c
	$(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) 

install: $(PROGNAME)
	install $(PROGNAME) $(BASE)/bin 

clean: 	
	rm -f $(PROGNAME)

C’est déjà un peu mieux que précédemment ! Pour voir le bon côté des choses, une cible install a été ajoutée : nous allons pouvoir supprimer la nôtre. Par contre, tout cela manque encore de portabilité.

Le premier problème est que l’installation se fait dans /usr/local. Il va nous falloir remplacer ceci par ${DESTDIR}/${PREFIX}

Le second problème est que ce Makefile présume que l’outil “install” est à la fois disponible et dans le PATH courant.

Nous pourrions - à nouveau - corriger ceci via un patch et le soumettre upstream. Nous l’avons déjà fait avec succès dans la version 1.0. Cette fois-ci, la voie sera différente : nous allons voir comment résoudre le problème en faisant des modifications automatisées du Makefile du projet avec pkgsrc.

On commence donc par enlever la target do-install, devenue inutile, et on utilise SUBST :

SUBST_CLASSES+= cleanup
SUBST_STAGE.cleanup= pre-configure
SUBST_FILES.cleanup= Makefile
SUBST_SED.cleanup+=  -e 's,/usr/local,${DESTDIR}/${PREFIX},g'
SUBST_SED.cleanup+=  -e 's,intall\ ,${INSTALL}\ ,g'                      

SUBST (Substitute pour les intimes) est basé sur sed. Vous aurez, je n’en doute pas, reconnu les expressions régulières permettant de faire deux remplacements :

( On remarquera d’ailleurs l’espace dans “install “, qui permet de ne pas matcher sur la chaine “install:” ! )

L’outil SUBST peut être appelé plusieurs fois dans notre fichier, c’est pourquoi on définit des classes. Ici, notre classe s’appellera “cleanup” (C’est un nom comme les autres, vous êtes pas raciste au moins ?) et aura lieu juste avant l’étape de configure (SUBST_STAGE). Elle sera appliquée au fichier Makefile (SUBST_FILES) et se compose de deux étapes de sed (SUBST_SED).

Toute l’idée de notre démarche, dans ce chapitre, est d’abstraire au maximum notre build par rapport à la plateforme.

La version finale du Makefile de notre package ressemble maintenant à ceci :

# $NetBSD$

VERS=           v2.1
DISTNAME=       truefalse-${VERS}
PKGNAME=        ${DISTNAME:S,-v,-,}
CATEGORIES=     misc
MASTER_SITES=   https://gitlab.com/iMil/truefalse/-/archive/${VERS}/

MAINTAINER=     truefalse@rancune.org
HOMEPAGE=       https://gitlab.com/iMil/truefalse/-/archive/${VERS}/
COMMENT=        First attempt at making a package
LICENSE=        original-bsd

INSTALLATION_DIRS=      bin

USE_TOOLS=      gmake
BUILD_TARGET=   truefalse

SUBST_CLASSES+= 		cleanup
SUBST_STAGE.cleanup= 	pre-configure
SUBST_FILES.cleanup= 	Makefile
SUBST_SED.cleanup+=  	-e 's,/usr/local,${DESTDIR}/${PREFIX},g'
SUBST_SED.cleanup+=  	-e 's,intall\ ,${INSTALL}\ ,g'                      

.include "../../devel/glib2/buildlink3.mk"
.include "../../mk/bsd.pkg.mk"

On peut vérifier que tout fonctionne comme prévu :

$bmake clean
$bmake distclean
$bmake ftech
$bmake makesum
$bmake
$sudo bmake deinstall
$sudo bmake install

La compilation se déroule sans encombre et le Makefile local de truefalse est bien modifié selon nos besoins :

$ cat work/truefalse-v2.1/Makefile
PROGNAME= truefalse
BASE= /home/rancune/pkgsrc/wip/truefalse/work/.destdir//home/rancune/pkg

CFLAGS=  $(shell pkg-config --cflags glib-2.0)
LDFLAGS= $(shell pkg-config --libs glib-2.0)

$(PROGNAME): $(PROGNAME).c
        $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)

install: $(PROGNAME)
        /usr/bin/install $(PROGNAME) $(BASE)/bin

clean:
        rm -f $(PROGNAME)

Ce chapitre conclut donc nos aventures avec truefalse. La semaine prochaine, Imil nous propose de découvrir comment packager un soft python simple : je ne sais pas vous, mais moi j’ai hâte ! Pkgsrc me plaît de plus en plus !

A bientôt,

Rancune.