Sun Mar 15 16:53:33 2020 UTC

Comment construire un premier paquet ?

Pourquoi vouloir construire un paquet ?

NuTyX dispose actuellement de quelques 1700 applications disponibles en binaires. C'est à la fois beaucoup et pas beaucoup en effet tous les jours ou presque sortent de nouvelles applications sous licence libre (ou pas)

Vous l'avez compris, vous ne trouverez jamais TOUTES les applications disponibles sur le net prêtes à être installées sur NuTyX. Rien que sur le site de sourceforge.net, on peut y trouver plus de 5000 applications toutes plateformes confondues. Si vous avez trouvez l'application de vos rêves, il faudra par un moyen ou un autre la compiler, l'installer et la faire fonctionner dans NuTyX. Pour cela nous allons vous demander de contribuer un petit peu. C'est vous qui allez construire le paquet... Si vous le voulez bien.

Compiler une application se résume souvent à faire les manipulations suivantes:

  • Trouver l'application qui n'existe pas sur NuTyX.
  • Télécharger les sources de l'application.
  • Vérifier la somme MD5 (vivement recommendé mais hélas pas toujours possible).
  • Extraire les sources dans un dossier de travail.
  • Entrer dans ce dossier de travail.
  • Vérifier que toutes les dépendances sont existantes dans NuTyX pour que la compilation de la nouvelle application se termine avec succès.
  • Taper les 3 commandes magiques (pas toujours le cas):
./configure --prefix=/usr
make
make install

La commande "make install" doit être lancée via le compte root.

Et voilà votre nouvelle application est compilée et disponible dans NuTyX.

C'est une façon de faire, mais comme vous pouvez le constater, elle n'est pas sans inconvénients:

  • Aucun moyen de retrouver les fichiers installés.
  • Aucun moyen de retrouver les informations sur le paquet installé cad le nom, la version, la description etc.
  • Aucun moyen de retrouver le paquet si vous souhaitez l'installer sur une autre machine.
  • Cette méthode est relativement fastidieuse, chaque opération doit impérativement être refaite en cas de mise à jour par exemple.
  • Aucun paquet n'a été créé, ce qui est très dommage si vous souhaitez le partager avec d'autres utilisateurs de NuTyX.
  • Votre NuTyX n'est plus vraiment propre puisque vous avez ajouté une application (ou même plusieurs si il y avait des dépendances. Cette application ne peut pas être gérée par le gestionnaire de paquets.

NuTyX dispose d'outils très faciles d'emploi qui vous faciliteront grandement la tâche et surtout qui vous permetteront de maintenir et intégrer la nouvelle application fraîchement compilée.

Je vous invite aussi à aller lire la FAQ pour prendre connaissance des modes de compilation sous NuTyX.

Quelles sont les connaissances nécessaires pour construire un paquet ?

Introduction

Pour pouvoir contribuer il ne faut pas être un programmeur averti. Quelques notions rudimentaires du langage BASH suffisent.

Si vous n'avez aucune idée du langage BASH, cet article vous expliquera les notions de base pour réaliser une recette sans se prendre la tête.

C'est le langage BASH qui est utilisé pour la rédaction d'une recette et la génération du paquet qui en découle. Le fait que BASH soit un langage de programmation peut effrayer plus d'un utilisateur potentiel pensant: "Je ne sais pas programmer..."

Cela ne devrait pas être le cas pour trois raisons:

  • BASH est un langage interprêté et non compilé, c'est à dire que les commandes tapées au clavier (ou lues depuis un fichier) sont directement exécutées sans qu'il ne soit nécessaire de construire un programme complet.
  • La syntaxe de BASH est très simple et intuitive à l'utilisation.
  • Une recette et la génération du paquet binaire qui en découle, utilise que très rarement des options compliquées du langage BASH.

Alors on y va Wink pour un petit cours sur la langage de programmation BASH.

Déclaration d'une variable

Déclarer une variable se limite à ceci:

name=monpaquet

On déclare la variable name en utilisant le signe égal et la valeur de la variable est à droite du signe égal: monpaquet

Utilisation d'une variable

On a appris comment déclarer une variable, c'est bien joli, mais comment fait-on pour l'utiliser, c'est à dire récupérer son contenu ?

Pour pouvoir récupérer le contenu d'une variable on utilise le sigle dollar ($) et éventuellement les accolades. Deux formes sont valides:

${name}
$name

Il est recommandé d'utiliser la première forme car si vous utilisez un nom de variable avec des sous-tirets, l'interprétation ne sera pas correcte:

name=xorg-libx11
_name=libX11
$name         # interprétation correcte
${_name}      # interprétation correcte
$_name        # mauvaise interprétation, ne fonctionnera pas

Pour voir le résultat de cette commande je vous propose de créer un petit fichier appelé DeclarVar comme suit:

name=kernel
echo "La variable name contient la valeur: ${name}"

Lancez maintenant la commande:

sh DeclareVar
La variable name contient la valeur: kernel

Variables prédéfinies utilisables dans une recette

Lorsque vous construisez une recette,vous aurez à votre disposition toute une série de variables prédéfinies.

PKG: Sans doute la plus utilisée, elle définit le dossier de destination des fichiers compilés. C'est donc dans ce dossier que se trouve la structure des fichiers prêts à être empaquetés.

SRC: Cette variable définit le dossier où toutes les sources sont extraites. Elle est donc aussi très utile lorsqu'il faut parcourir des sous-dossiers et revenir à la fin d'une boucle au dossier de départ, c'est à dire dans le dossier défini par SRC. C'est aussi la variable qui définit le dossier courant dans la fonction principale de la recette.

MAKEFLAGS: Cette variable n'est pas très souvent utilisée. Elle est initialisée dans le fichier de configuration de pkgmk. On verra ça en détail dans un autre article, il faut juste savoir pour l'instant qu'elle permet d'influencer la compilation parallèle.

Il en existe d'autres mais personnellement je n'en vois pas l'utilité dans la construction d'une recette.

Déclaration d'un tableau

Pour déclarer un tableau de chaîne (ou autre) on va ajouter des parenthèses:

source=(firefox.png firefox.desktop)

Le tableau source contient 2 variables: firefox.png et firefox.desktop. Si on prend le tableau source de la recette du kernel, on a un joli exemple:

source=(http://download.virtualbox.org/virtualbox/${VB_VERSION}/VirtualBox-${VB_VERSION}-${VB_BUILD}-Linux_${VB_ARCH}.run
	http://fr.download.nvidia.com/XFree86/Linux-${_ARCH}/${NVIDIA_VERSION}/NVIDIA-Linux-${_ARCH}-${NVIDIA_VERSION}.run
	http://www.kernel.org/pub/linux/kernel/v3.0/linux-${_BaseVersion}.tar.bz2 config_64 config)

Chaque ligne est une variable que l'on peut appeler en utilisant la syntaxe:

echo "$(source[1])"

Vous noterez que chaque variable peut à son tour contenir d'autres variables pour autant qu'elles soient définies au préalable.

Déclaration d'une fonction

Pour déclarer une fonction, c'est presque aussi simple, on utilise les parenthèses pour spécifier le nom de la fonction, la fonction est toujours délimitée par les accolades { et }. Petit exemple:

build() {
cd $name-$version
./configure --prefix=/usr
make
make DESTDIR=$PKG install
}

Comme on peut le voir, c'est bel et bien le contenu d'une recette minimale (sans la déclaration des variables). On peut y voir l'utilisation incontournable de la variable PKG.

Qu'est-ce qu'un port ?

Introduction

Le port est un dossier contenant un certain nombre de fichiers (au minimum 1) nécessaire pour la construction d'un paquet. La commande pkgmk permet de "construire" le paquet qui sera ensuite installable.

Pour être fonctionnel, ce dossier doit contenir au minimum un fichier appelé Pkgfile. C'est grâce à ce fichier que la construction du paquet peut se faire. Le contenu de Pkgfile contient toutes les informations nécéssaires pour la construction ou plus exactement la compilation du paquet depuis les sources.

Le nom port est emprunté du monde BSD où un port se réfère à un logiciel "porté" sur un système d'exploitation ou une plateforme. Dans notre cas, le port est simplement la définition de la construction d'un paquet.

Syntaxe minimale d'un port

Les informations minimales pour pouvoir produire le binaire sont:

  • name spécifie le nom du paquet qui sera construit.
  • version spécifie la version des sources du paquet.
  • release spécifie la N'ième tentative de construction du paquet. Sa valeur commence donc toujours à 1
  • source contient l'adresse des sources du paquet que l'on souhaite empaqueter.
  • build() la fonction qui contient la recette proprement dîte.

Un petit exemple avec commentaires:

# Nom du paquet
name=gnome-terminal

# Version du paquet
version=2.6.4

# Release du paquet
release=1

# Emplacement des sources du paquet qui sera empaqueté
source=(https://ftp.gnome.org/pub/gnome/sources/$name/${version%.*}/$name-$version.tar.bz2)

# Définition de la recette proprement dite, souvent constitué des trois commandes standards
build() {
cd $name-$version
./configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info
make
make DESTDIR=$PKG install
}

Si vous comparez cet exemple avec un port officiel de NuTyX, vous constaterez que ce dernier contient plus d'informations. C'est ce que nous verrons dans le prochain paragraphe. Une ligne vous a peut-être attiré votre attention:

https://ftp.gnome.org/pub/gnome/sources/$name/${version%.*}/

La syntaxe ${version%.*} permet de substituer une valeur à N chiffres en une valeur à N-1 chiffres. C'est très souvent le cas pour les sources des paquets gnome. Dans notre exemple donc, la ligne:

https://ftp.gnome.org/pub/gnome/sources/$name/${version%.*}/

est identique à

https://ftp.gnome.org/pub/gnome/sources/$name/2.6/

puisque la variable version=2.6.4

Exemple pratique d'une recette

Le fichier libxfce4util/Pkgfile

description="libxfce4util, base library for Xfce"
url="http://docs.xfce.org/"

maintainer="git.xfce.org/xfce/xfce4-libutils"
packager="tnut "
contributors="Tyrry, Geantbrun"

makedepends=(glib intltool)

name=libxfce4util
version=4.14.1
release=1
source=(http://archive.xfce.org/src/xfce/${name}/${version%.*}/${name}-$version.tar.bz2)

build() {
cd ${name}-$version
./configure --prefix=/usr \
--disable-static
make
make DESTDIR=$PKG install
}

Si vous souhaitez que le serveur de construction puisse construire le paquet sans soucis, il est important de mentionner toutes les dépendances nécéssaires à la compilation de votre paquet, et ce en partant toujours d'une NuTyX de base. En effet le serveur construira toujours le paquet en partant de la même base.

La ligne makedepends=(..) est utilisée à cet effet, elle définie donc les dépendances nécéssaires à la compilation du paquet. On y indique les dépendances nécéssaires séparées par un espace.Laughing.

Construire votre premier paquet

Nous connaissons les raisons de contribuer, les connaissances requises, le format minimum d'une recette et enfin quelles sont les recettes existantes.

Il est temps de passer à l'action,de construire et d'installer son premier paquet dans les règles de l'art (de NuTyX) Laughing.

Nous allons d'abord voir ensemble comment construire un premier paquet binaire NuTyX au format <MonpaquetDateArch.cards.tar> depuis son code source sans entrer dans les détails de configuration pour l'instant.

Ce paquet fonctionnel pourra être installé et désinstallé dans votre NuTyX grâce à ses outils de gestion de paquets.

Vous aurez besoin des outils cards.devel installés pour compiler celui-ci.

Ce tutoriel simple peut être testé sur votre NuTyX quelle que soit sa configuration.

La recette du paquet choisi est un petit éditeur de texte ne nécessitant aucune dépendance.

[Important] Pour ce paquet, on n'utilisera pas d'environnement isolé aussi appelé chroot. On verra dans un prochain article, comment construire dans cet environnement isolé. Parce que c'est la seule methode qui fonctionnera si l'on doit construire un paquet ayant des dépendances.

Un minimum d'explications

Tous les paquets disponibles sous NuTyX utilisent une recette.

Cette recette (Pkgfile) est rangée dans un dossier au nom du paquet qui est lui-même rangé dans une collection.

Les Collections se trouvent (par défaut) dans le dossier /usr/ports.

La recette

On crée les répertoires nécessaires: la collection "perso" et le dossier du paquet.

sudo mkdir -p /usr/ports/perso/nano
echo '
description="Command line Text Editor"
maintainer="Nano team"
packager="François Perrin francois dot perrin at myworld dot com"
url="http://www.nano-editor.org/"

name=nano
version=2.7.2
release=1

source=(${url}/dist/v${version:0:3}/$name-$version.tar.xz)

build() {
cd $name-$version
./configure --prefix=/usr \
--sysconfdir=/etc \
--enable-utf8 \
--enable-color \
--enable-multibuffer \
--enable-nanorc \
--docdir=/usr/share/doc/$name-$version
make
make DESTDIR=$PKG install
rm $PKG/usr/share/info/dir
}' > /usr/ports/perso/nano/Pkgfile

Installation des paquets de développement

get cards.devel

Compilation du paquet

cd /usr/ports/perso/nano
sudo pkgmk -d

Installation du paquet

sudo pkgadd nano1*

Les différents fichiers de configuration

Le fichier /etc/cards.conf

Ce fichier est toujours présent dans une installation NuTyX.

C'est un peu "la colonne vertébrale" de votre NuTyX.

C'est le fichier /etc/cards.conf qui reflètera votre façon d'utiliser NuTyX.

Toutes les collections que vous souhaitez utiliser dans votre NuTyX peuvent y être spécifiées sous 2 formes possibles:

  1. exemple de configuration de la collection cli en binaires depuis un serveur de dépot distant
    dir /var/lib/pkg/depot/cli|http://downloads.nutyx.org
  2. exemple de configuration de la collection cli en ports locals
    dir /usr/ports/cli

Il est également responsable de la liste des paquets que vous souhaitez conserver lorsque vous exécutez la commande:

cards base -r
Et enfin il spécifie quelles locales seront installées

Vous trouverez plus d'informations en consultant le manuel de cards.conf

man cards.conf

Le fichier /etc/pkgmk.conf

Ce fichier est utilisé lors de la compilation de nouveaux ports. Il spécifie toutes les variables reconnues par la commande pkgmk

Veuillez prendre note des différentes variables qui sont à votre disposition en consultant le manuel de pkgmk.conf

man pkgmk.conf
Exemple de fichier /etc/pkgmk.conf
export CFLAGS="-O2 -pipe"
export CXXFLAGS="${CFLAGS}"

case ${PKGMK_ARCH} in
        "x86_64")
		export MAKEFLAGS="-j$(getconf _NPROCESSORS_ONLN)"
                ;;
        "i686")
                export CFLAGS="${CFLAGS} -m32"
                export CXXFLAGS="${CXXFLAGS} -m32"
                export LDFLAGS="${LDFLAGS} -m32"
                ;;
        *)
                echo "Unknown architecture selected! Exiting."
                exit 1
                ;;
esac
# Those settings are typically set for packaging
# without sub packages and only french locale
# They are also the default ones
#
# PKGMK_GROUPS=()
# PKGMK_LOCALES=(fr)
# PKGMK_COMPRESS_PACKAGE="no"
# PKGMK_CLEAN="yes"
# PKGMK_IGNORE_FOOTPRINT="yes"
# PKGMK_KEEP_SOURCES="no"
# PKGMK_SOURCE_DIR="$PWD"
# PKGMK_WORK_DIR="$PWD/work"
# PKGMK_IGNORE_REPO="yes"
# PKGMK_IGNORE_COLLECTION="yes"
# PKGMK_IGNORE_RUNTIMEDEPS="yes"

Conclusion

Nous voilà prêts pour la compilation de paquets. Nous allons maintenant voir ce qu'est une collection.