pkgsrc (4/6)

Previous Next

Bienvenue à nouveau sur ce blog et sur mes prises de notes sur les vidéos d’Imil. Prêts pour ce nouveau chapitre ? Après notre petit jeu de rôles des épisodes précédents, nous allons maintenant nous lancer dans le packaging d’une véritable application Python sous son haut patronat. Comme toujours, vous pouvez consulter la vidéo [ici]

Enfin … ici … ici … Dès qu’elle sera disponible sur YouTube ! ^^’

Notre objectif ? Archey 4

Il existe tout un tas de petits programmes permettant d’afficher fièrement son système devant ses copains. Après tout, nous passons de longues heures à ajuster tout ça aux petit oignons, alors autant le montrer avec classe non ? Parmi ces outils, on peut citer les deux plus courants : neofetch et screenfetch .

En voici un petit exemple :

imageseb (Tiens ? Il est pourri l’affichage de mon shell … faudra que je regarde pourquoi !)

L’appli que nous allons commencer à packager aujourd’hui est un autre de ces outils, assez complet :

Il s’agit de archey4, qui est disponible sur Github

imageseb

(Source: Github du projet)

Comme vous pouvez le voir, l’appli indique quelques infos particulières : Température, IP, etc.

Mais, et ce sera l’occasion d’apprendre comment pkgsrc le gère, elle est écrite en Python.

Préparons notre package :

Puisque nous ne sommes pas (encore) habilités à créer directement des packages officiels du système FreeBSD, nous allons utiliser pkgsrc-wip comme expliqué dans les épisodes précédents.

Comment ? Vous ne savez pas ce qu’est wip ??? Filez donc lire l’épisode 1 !

Bon, je vous ré-explique en quelques mots, mais que je nous y reprenne plus ! Wip, c’est un repository permettant aux gens de faire des packages et de les rendre disponibles à tout le monde. L’accès y est plus “simple” dans le sens où il suffit d’y montrer patte blanche auprès de Thomas Klausner pour pouvoir y avoir accès et publier votre package.

Avant de se lancer dans un package, il est de bon ton de vérifier que celui-ci n’existe pas déjà ! Cela évite du travail inutile et de la frustration. On commence donc par effectuer une recherche avec pkgfind :

$ pkgfind archey

Pas de résultat ? Parfait. Lançons-nous !

Comme la dernière fois, nous allons commencer par installer wip via git, et créer le dossier pour notre package :

$ cd /usr/pkgsrc

$ git clone --depth 1 git://wip.pkgsrc.org/pkgsrc-wip.git wip
Cloning into 'wip'...
remote: Enumerating objects: 44337, done.
remote: Counting objects: 100% (44337/44337), done.
remote: Compressing objects: 100% (38947/38947), done.
remote: Total 44337 (delta 3991), reused 30831 (delta 3407), pack-reused 0
Receiving objects: 100% (44337/44337), 26.86 MiB | 375.00 KiB/s, done.
Resolving deltas: 100% (3991/3991), done.
Updating files: 100% (36802/36802), done.

$ mkdir wip/archey4

Une petite précision ici : On considère que le nom du package est archey4 … Et donc que le chiffre “4” fait partie du nom du package ! Ce n’est pas un numéro de version, sinon nous ne l’aurions pas mis dans le nom du répertoire.

Et, tout comme les fois précédentes, on utilise url2pkg pour créer le template de notre projet :

$ cd /usr/pkgsrc/wip/archey4

$ url2pkg https://github.com/HorlogeSkynet/archey4/archive/refs/tags/v4.13.4.zip
===> Cleaning for archey4-4.13.4
=> Bootstrap dependency digest>=20211023: found digest-20220214
WARNING: [license.mk] Every package should define a LICENSE.
=> Fetching archey4-4.13.4.zip
Requesting https://github.com/HorlogeSkynet/archey4/archive/refs/tags/v4.13.4.zip
Redirected to https://codeload.github.com/HorlogeSkynet/archey4/zip/refs/tags/v4.13.4
Requesting https://codeload.github.com/HorlogeSkynet/archey4/zip/refs/tags/v4.13.4
   156 KiB    1.38 MiB/s
160197 bytes retrieved in 00:00 (1.38 MiB/s)
=> Checksum BLAKE2s OK for archey4-4.13.4.zip
=> Checksum SHA512 OK for archey4-4.13.4.zip
===> Installing dependencies for archey4-4.13.4
=> Tool dependency cwrappers>=20150314: found cwrappers-20220403
=> Tool dependency checkperms>=1.1: found checkperms-1.12
===> Skipping vulnerability checks.
WARNING: No /var/db/pkg/pkg-vulnerabilities file found.
WARNING: To fix run: `/usr/pkg/sbin/pkg_admin -K /var/db/pkg fetch-pkg-vulnerabilities'.
===> Overriding tools for archey4-4.13.4
===> Extracting for archey4-4.13.4

Remember to run pkglint when you're done.
See ../../doc/pkgsrc.txt to get some help.

Une petite chose importante à ce stade. Lorsqu’on package un logiciel, on ne se base en général jamais sur la branche “main” ou “master”. Et pour cause : celle-ci change beaucoup trop souvent ! On se base sur des versions que l’on peut identifier : ici les tags dans le cas de Github.

Voyons voir à quoi ressemble le Makefile généré par url2pkg :

# $NetBSD$

GITHUB_TAG=     refs/tags/v${PKGVERSION_NOREV}
DISTNAME=       archey4-4.13.4
PKGNAME=        ${PYPKGPREFIX}-${DISTNAME}
CATEGORIES=     python # TODO: add primary category
MASTER_SITES=   ${MASTER_SITE_GITHUB:=HorlogeSkynet/}
EXTRACT_SUFX=   .zip

MAINTAINER=     INSERT_YOUR_MAIL_ADDRESS_HERE # or use pkgsrc-users@NetBSD.org
HOMEPAGE=       https://github.com/HorlogeSkynet/archey4
COMMENT=        Archey is a simple system information tool written in Python
#LICENSE=       GPLv3 # TODO: from setup.py; needs to be adjusted

DEPENDS+=       # TODO: distro~=1.3>=0
DEPENDS+=       # TODO: netifaces~=0.10>=0

USE_LANGUAGES=  # none

.include "../../lang/python/egg.mk"
.include "../../mk/bsd.pkg.mk"

Ce Makefile est légèrement différent de celui que nous avions obtenu lorsque nous packagions le désormais célèbre truefalse.

Tout d’abord, on peut noter que pkgsrc a détecté tout seul que nous packagions une appli python, et s’est adapté. C’est remarquablement bien fait : il a lu le setup.py du soft et a rempli tout seul certains champs, comme la licence (LICENSE) ou les dépendances.

Ensuite, pkgsrc a également pris en compte le fait que cette url pointait vers le site de Github. Etant donné que c’est un site “bien connu”, pkgsrc utilise des variables pour ce cas particulier telles que le MASTER_SITE_GITHUB. C’est plutôt bien pensé !

On remplit dès maintenant les champs simples : CATEGORIES, MAINTAINER, HOMEPAGE, LICENSE … pas de grande révolution pour le moment. C’est, pour être franc, une des choses que j’apprécie beaucoup sur cet outil que je découvre avec vous : tout à l’air bien pensé, bien intégré, et ça limite beaucoup nos difficultés !

Petit rappel : pour les licences, on peut en trouver la liste dans “/usr/pkgsrc/mk/licences.mk”. Il ne faut pas mettre n’importe quoi ! C’est normalisé !

Voici à quoi ressemble désormais notre Makefile :

# $NetBSD$

GITHUB_TAG=     refs/tags/v${PKGVERSION_NOREV}
DISTNAME=       archey4-4.13.4
PKGNAME=        ${PYPKGPREFIX}-${DISTNAME}
CATEGORIES=     sysutils
MASTER_SITES=   ${MASTER_SITE_GITHUB:=HorlogeSkynet/}
EXTRACT_SUFX=   .zip

MAINTAINER=     maintainer@rancune.org
HOMEPAGE=       https://github.com/HorlogeSkynet/archey4
COMMENT=        Archey is a simple system information tool written in Python
LICENSE=        gnu-gpl-v3

DEPENDS+=       # TODO: distro~=1.3>=0
DEPENDS+=       # TODO: netifaces~=0.10>=0

USE_LANGUAGES=  # none

.include "../../lang/python/egg.mk"
.include "../../mk/bsd.pkg.mk"

La récupération des paquets, lorsque l’on fait un make fetch, se fait par défaut à partir de la chaîne :

${DISTNAME}${EXTRACT_SUFX}

Par défaut, le suffixe est “.tar.gz” : encore une fois, pkgsrc a fait du bon boulot !

Penchons nous maintenant plus spécifiquement sur les aspects “python” de la chose …

La gestion des paquets Python sous pkgsrc

Gestion des versions de python

Pkgsrc permet de faire cohabiter différentes versions de python dans notre OS, et donc différentes versions d’un même soft pour chacune de ces versions.

Ceci est réalisé grâce au nom du paquet (le PKGNAME) composé de la façon suivante :

PKGNAME=        ${PYPKGPREFIX}-${DISTNAME}

Si, par exemple, nous disposons des versions 2.7, 3.2 et 3.9 de Python, ce paquet pourra être installé en tant que :

Et cela s’appliquera, bien entendu, à toutes les dépendances nécessaires !

Pour que les choses se fassent de la façon correcte, nous allons donc renommer notre répertoire et suivre la convention :

$ cd /usr/pkgsrc/wip
$ mv archey4 py-archey4

Voilà ! C’est mieux non ?

Les dépendances du package

Concentrons nous plus spécifiquement sur les dépendances de notre package. Elles sont présentes dans les deux lignes suivantes du Makefile et ont été extraites du setup.py :

DEPENDS+=       # TODO: distro~=1.3>=0
DEPENDS+=       # TODO: netifaces~=0.10>=0

Avant toute chose, nous vérifions que ces packages python existent déjà dans pkgsrc, sans quoi il nous faudra les packager elles-aussi ! ( Tu la sens venir la grosse galère ??? )

La main un peu tremblante, nous utilisons pkgfind :

$ pkgfind py-distro
devel/py-distro: OS platform information API

$ pkgfind py-netifaces
net/py-netifaces: Portable access to network interfaces from Python

Bon, pour cette fois-ci, tout ira bien ! Ceci dit, si cela n’avait pas été le cas, cela n’aurait pas été un drame … Juste un peu plus de travail !

Nous pouvons donc modifier notre Makefile une dernière fois pour ajouter les dépendances :

DEPENDS+=	${PYPKGPREFIX}-distro>=1.3:../../devel/py-distro
DEPENDS+=	${PYPKGPREFIX}-netifaces>=0.10:../../net/py-netifaces

C’est quand même terriblement chouette de se dire que nous n’avons pas besoin de gérer les versions de python non ?

Les finitions

Deux dernière choses avant de nous lancer. La première concerne cette ligne :

USE_LANGUAGES=  # none

Cette variable sert habituellement à préciser quel compilateur doit être utilisé pour un package. Les choix sont les suivants :

	c99, c++, c++03, gnu++03, c++0x, gnu++0x, c++11, gnu++11,
	c++14, gnu++14, c++17, gnu++17, c++20, gnu++20, fortran,
	fortran77, java, objc, obj-c++, and ada.

Ici, pas besoin ! On enlève la ligne !

La seconde chose concerne les includes utilisés en fin de Makefile. Lorsqu’un projet utilise setup.py (les setup-tools et les “eggs”), on inclue egg.mk comme indiqué dans la documentation de pkgsrc. Comme vous pouvez le voir, url2pkg l’a déjà fait pour nous.

Mais nous pouvons également inclure ../../lang/python/application.mk !

Comme il est assez court, en voici le contenu :

# $NetBSD: application.mk,v 1.13 2020/03/24 04:40:34 rillig Exp $
#
# Replace the #! interpreter for Python scripts.
#
# This mk fragment should be included in all python packages that
# install python scripts, or at least those that don't use setuptools
# or some other mechanism to set the real path.  Specifically, it is
# reasonable to include both egg.mk and application.mk.
#
# Package-settable variables:
#
# REPLACE_PYTHON
#       A list of filename patterns for Python scripts to be installed,
#       relative to ${WRKSRC}.
#
# Keywords: python
#

.include "../../lang/python/pyversion.mk"

.if defined(REPLACE_PYTHON)
REPLACE_INTERPRETER+=   python
REPLACE.python.old=     .*python3\{0,1\}[^ ]*
REPLACE.python.new=     ${PYTHONBIN}
REPLACE_FILES.python=   ${REPLACE_PYTHON}
.endif

Ce petit fichier permet de remplacer dans tous les fichiers python le chemin vers l’interpréteur (probablement codé en dur ^^’).

Là, j’avoue que ça m’a scotché. C’est très très bien pensé !!!

Et c’est parti !!!

Il est maintenant temps de nous lancer. La version actuelle de notre Makefile est la suivante :

# $NetBSD$

GITHUB_TAG=     refs/tags/v${PKGVERSION_NOREV}
DISTNAME=       archey4-4.13.4
PKGNAME=        ${PYPKGPREFIX}-${DISTNAME}
CATEGORIES=     sysutils
MASTER_SITES=   ${MASTER_SITE_GITHUB:=HorlogeSkynet/}
EXTRACT_SUFX=   .zip

MAINTAINER=     maintainer@rancune.org
HOMEPAGE=       https://github.com/HorlogeSkynet/archey4
COMMENT=        Archey is a simple system information tool written in Python
LICENSE=        gnu-gpl-v3

DEPENDS+=       ${PYPKGPREFIX}-distro>=1.3:../../devel/py-distro
DEPENDS+=       ${PYPKGPREFIX}-netifaces>=0.10:../../net/py-netifaces

.include "../../lang/python/egg.mk"
.include "../../lang/python/application.mk"
.include "../../mk/bsd.pkg.mk"

On commence par vérifier que tout est bien propre : on ne sait jamais.

$ make clean
===> Cleaning for py39-archey4-4.13.4

La version de python est correctement indiquée, tout cela s’annonce plutôt bien ! La version par défaut de python utilisée sur ce système est la version 3.9. Nous pourrions, si nous le voulions, la modifier en ajoutant au fichier mk.conf la ligne :

PYTHON_VERSION_DEFAULT= 37

Comme la semaine dernière, nous allons simuler une installation :

$ make stage-install
[...]
cd: can't cd to /usr/pkgsrc/wip/archey4/work/py39-archey4-refs/tags/v4.13.4/
*** Error code 2

Stop.
make[1]: stopped in /usr/pkgsrc/wip/archey4
*** Error code 1

Stop.
make: stopped in /usr/pkgsrc/wip/archey4

Il s’agit là d’un petit problème de chemin : Nous allons corriger cela en renseignant la variable WRKSRC :

# $NetBSD$

GITHUB_TAG=     refs/tags/v${PKGVERSION_NOREV}
DISTNAME=       archey4-4.13.4
PKGNAME=        ${PYPKGPREFIX}-${DISTNAME}
CATEGORIES=     sysutils
MASTER_SITES=   ${MASTER_SITE_GITHUB:=HorlogeSkynet/}
EXTRACT_SUFX=   .zip

MAINTAINER=     maintainer@rancune.org
HOMEPAGE=       https://github.com/HorlogeSkynet/archey4
COMMENT=        Archey is a simple system information tool written in Python
LICENSE=        gnu-gpl-v3

DEPENDS+=       ${PYPKGPREFIX}-distro>=1.3:../../devel/py-distro
DEPENDS+=       ${PYPKGPREFIX}-netifaces>=0.10:../../net/py-netifaces

WRKSRC=		${WRKDIR}/${DISTNAME}

.include "../../lang/python/egg.mk"
.include "../../lang/python/application.mk"
.include "../../mk/bsd.pkg.mk"

Et on y retourne … Sans oublier de remettre à jour PLIST !

$ make clean
$ make
$ make print-PLIST > PLIST
$ make stage-install
$ sudo make install

Tout compile et l’installation a fonctionné !

Test et conclusion :

Il est maintenant temps de lancer archey et de recevoir la juste récompense pour notre travail :

$ archey

WARNING: [archey.entries.temperature] [sysctl]: Couldn't fetch temperature from CPU sensors 
(sysctl: top level name 'dev' in 'dev.cpu.0.temperature' is invalid). Please be sure to load the 
corresponding kernel driver beforehand (`kldload coretemp` for Intel or `kldload amdtemp` for AMD`).
sysctl: second level name 'memsize' in 'hw.memsize' is invalid
Traceback (most recent call last):
  File "/usr/pkg/bin/archey", line 33, in <module>
    sys.exit(load_entry_point('archey4==4.13.4', 'console_scripts', 'archey')())
  File "/usr/pkg/lib/python3.9/site-packages/archey/__main__.py", line 168, in main
    for entry_instance in mapper(_entry_instantiator, available_entries):
  File "/usr/pkg/lib/python3.9/concurrent/futures/_base.py", line 609, in result_iterator
    yield fs.pop().result()
  File "/usr/pkg/lib/python3.9/concurrent/futures/_base.py", line 439, in result
    return self.__get_result()
  File "/usr/pkg/lib/python3.9/concurrent/futures/_base.py", line 391, in __get_result
    raise self._exception
  File "/usr/pkg/lib/python3.9/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/usr/pkg/lib/python3.9/site-packages/archey/__main__.py", line 144, in _entry_instantiator
    return Entries[entry.pop('type')].value(
  File "/usr/pkg/lib/python3.9/site-packages/archey/entries/ram.py", line 23, in __init__
    used, total = self._get_used_total_values()
  File "/usr/pkg/lib/python3.9/site-packages/archey/entries/ram.py", line 44, in _get_used_total_values
    return self._run_sysctl_and_vmstat()
  File "/usr/pkg/lib/python3.9/site-packages/archey/entries/ram.py", line 96, in _run_sysctl_and_vmstat
    check_output(
  File "/usr/pkg/lib/python3.9/subprocess.py", line 424, in check_output
    return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
  File "/usr/pkg/lib/python3.9/subprocess.py", line 528, in run
    raise CalledProcessError(retcode, process.args,
subprocess.CalledProcessError: Command '['sysctl', '-n', 'hw.memsize']' returned non-zero exit status 1.

Mmmh … L’application fonctionne, mais elle n’est visiblement pas faite pour NetBSD !

dev.cpu.0.temperature … Pas de cela ici mon bon monsieur ! C’est un NetBSD ici, pas un FreeBSD !

Oui, c’est frustrant, je suis bien d’accord. Alors rendez-vous la semaine prochaine pour la suite de nos aventures et le dénouement de ce cliffhanger diabolique …

A bientôt,

Rancune.