Construire des paquets RPM avec Mock
Il y a quelque temps, j'ai décidé de migrer l'ensemble de mes postes de travail tournant sous OpenSUSE vers Rocky Linux, un clone de Red Hat Enterprise Linux. La plupart des paquets dont j'ai normalement besoin pour configurer un poste de travail cohérent sont fournis soit par les dépôts de paquets officiels de la distribution, soit par des dépôts tiers comme EPEL, RPMFusion ou ELRepo.
Or, il arrive tôt ou tard qu'un paquet que j'utilise au quotidien n'est disponible nulle part. Dans ce cas, ce n'est pas une mauvaise idée de retourner aux sources - littéralement - et de construire moi-même mes paquets RPM.
Rocky Linux, Red Hat, Fedora et EPEL
Étant donné que Rocky Linux est un clone binairement compatible à Red Hat Enterprise Linux et que cette dernière peut être considérée comme une Fedora stabilisée, la solution pragmatique consiste à partir d'un paquet SRPM (Source RPM) de Fedora pour construire mes propres paquets binaires. C'est d'ailleurs à quelques menus détails près la démarche des mainteneurs du dépôt EPEL (Extra Packages for Enterprise Linux).
L'environnement de construction
Le premier problème qui se pose, c'est la mise en place d'un environnement de construction.
-
La compilation d'un paquet nécessite l'installation de toutes les dépendances de construction, ce qui fait que je me retrouve assez rapidement à spammer mon système de tout un fatras de paquets de développement.
-
Non content de cela, cette manière de procéder me limite à construire des paquets pour la version et l'architecture spécifique que j'utilise, en l'occurence Rocky Linux dans sa version 8.6 sur une architecture
x86_64.
C'est là où Mock entre en jeu. Mock est une surcouche à rpmbuild qui
simplifie de manière significative la construction d'un paquet RPM.
-
La construction a lieu dans un environnement
chrootbien isolé, ce qui m'évite d'encombrer mon système voire même de le mettre en péril. -
En dehors de cela, Mock permet également de compiler des paquets pour d'autres distributions dans plusieurs déclinaisons de versions et d'architectures.
Installation de Mock
L'utilitaire mock est fourni par le dépôt tiers EPEL :
L'installation du paquet a créé un nouveau groupe système mock :
J'ajoute mon utilisateur à ce groupe :
Je me reconnecte et je vérifie si j'appartiens bien à ce groupe :
Un peu de pratique
En guise de démonstration, je vais construire un paquet binaire pour le client OwnCloud.
Pas de client OwnCloud pour Red Hat
Pour des raisons mystérieuses, l'équipe de OwnCloud ne propose pas le moindre paquet binaire pour Red Hat Enterprise Linux et les distributions dérivées, et le paquet n'est pas fourni par le dépôt EPEL non plus. Qu'à cela ne tienne, on va donc chasser l'ours à mains nues.
Le portail rpm.pbone.net est une excellente adresse pour trouver des paquets SRPM (Source RPM) :
-
Je crée un répertoire local
~/SRPMS. -
J'ouvre la page d'accueil du site dans un navigateur Web.
-
Je sélectionne Advanced RPM Search.
-
Je coche Fedora 35 et je lance une recherche sur
owncloud-client. -
Dans la liste des résultats, j'opte pour
owncloud-client-2.10.1-1.fc35.src.rpm. -
Je copie l'adresse du lien et je télécharge le paquet vers
~/SRPMSen utilisantwget.
J'installe le paquet en tant qu'utilisateur simple (et non pas en tant que
root) :
L'installation a créé une arborescence ~/rpmbuild qui ressemble à ceci :
$ tree ~/rpmbuild/
/home/kikinovak/rpmbuild/
├── SOURCES
│ ├── 69-sync-inotify.conf
│ ├── ownCloud-2.10.1.7389.tar.xz
│ ├── owncloud.appdata.xml
│ ├── owncloud-client-2.10.1.7389-gcc12.patch
│ ├── owncloud-client-2.9.0-syslibs.patch
│ └── ownCloud.conf
└── SPECS
└── owncloud-client.spec
2 directories, 7 files
Je me rends dans le répertoire rpmbuild/SPECS pour préparer les
sources :
$ cd ~/rpmbuild/SPECS/
$ rpmbuild -bs owncloud-client.spec
Écrit : /home/kikinovak/rpmbuild/SRPMS/owncloud-client-2.10.1-1.el8.src.rpm
La commande rpmbuild ci-dessus a créé quelques répertoires supplémentaires,
notamment rpmbuild/SRPMS :
$ tree ~/rpmbuild/
/home/kikinovak/rpmbuild/
├── BUILD
├── BUILDROOT
├── RPMS
├── SOURCES
│ ├── 69-sync-inotify.conf
│ ├── ownCloud-2.10.1.7389.tar.xz
│ ├── owncloud.appdata.xml
│ ├── owncloud-client-2.10.1.7389-gcc12.patch
│ ├── owncloud-client-2.9.0-syslibs.patch
│ └── ownCloud.conf
├── SPECS
│ └── owncloud-client.spec
└── SRPMS
└── owncloud-client-2.10.1-1.el8.src.rpm
6 directories, 8 files
Je me rends dans le répertoire SRPMS :
Le répertoire /etc/mock contient les configurations respectives de toutes les
cibles possibles. Voyons quels sont les profils disponibles pour la
distribution que j'utilise :
$ ls -1 /etc/mock/rocky*
/etc/mock/rocky-8-aarch64.cfg
/etc/mock/rocky-8-x86_64.cfg
/etc/mock/rocky-9-aarch64.cfg
/etc/mock/rocky-9-ppc64le.cfg
/etc/mock/rocky-9-s390x.cfg
/etc/mock/rocky-9-x86_64.cfg
/etc/mock/rocky+epel-8-aarch64.cfg
/etc/mock/rocky+epel-8-x86_64.cfg
/etc/mock/rocky+epel-9-aarch64.cfg
/etc/mock/rocky+epel-9-ppc64le.cfg
/etc/mock/rocky+epel-9-s390x.cfg
/etc/mock/rocky+epel-9-x86_64.cfg
Je souhaite construire un paquet pour Rocky Linux 8 sur une plateforme x86_64.
Je sais que mon paquet présente quelques dépendances disponibles dans le dépôt
EPEL, je vais donc lancer la construction de mon paquet en optant pour le
profil rocky+epel-8-x86_64 :
$ mock -r rocky+epel-8-x86_64 --rebuild owncloud-client-2.10.1-1.el8.src.rpm
INFO: mock.py version 3.0 starting (python version = 3.6.8, NVR = mock-3.0-1.el8)
Start(bootstrap): init plugins
INFO: selinux enabled
Finish(bootstrap): init plugins
Start: init plugins
INFO: selinux enabled
Finish: init plugins
INFO: Signal handler active
Start: run
INFO: Start(owncloud-client-2.10.1-1.el8.src.rpm) Config(rocky+epel-8-x86_64)
Start: clean chroot
Finish: clean chroot
Start(bootstrap): chroot init
INFO: calling preinit hooks
INFO: enabled root cache
INFO: enabled package manager cache
Start(bootstrap): cleaning package manager metadata
Finish(bootstrap): cleaning package manager metadata
INFO: enabled HW Info plugin
Mock Version: 3.0
INFO: Mock Version: 3.0
Start(bootstrap): dnf install
...
Mock sous le capot
La commande mock se charge de deux choses ici :
-
Télécharger et installer un environnement de construction cohérent.
-
Construire le paquet à l'intérieur de cet environnement isolé du système.
Au bout d'une bonne dizaine de minutes, j'obtiens une série de paquets RPM
proprement rangés dans l'arborescence /var/lib/mock, dans le répertoire qui
correspond à ma cible :
$ cd /var/lib/mock/rocky+epel-8-x86_64/result/
$ ls -1 *.rpm
owncloud-client-2.10.1-1.el8.src.rpm
owncloud-client-2.10.1-1.el8.x86_64.rpm
owncloud-client-caja-2.10.1-1.el8.x86_64.rpm
owncloud-client-debuginfo-2.10.1-1.el8.x86_64.rpm
owncloud-client-debugsource-2.10.1-1.el8.x86_64.rpm
owncloud-client-devel-2.10.1-1.el8.x86_64.rpm
owncloud-client-dolphin-2.10.1-1.el8.x86_64.rpm
owncloud-client-dolphin-debuginfo-2.10.1-1.el8.x86_64.rpm
owncloud-client-libs-2.10.1-1.el8.x86_64.rpm
owncloud-client-libs-debuginfo-2.10.1-1.el8.x86_64.rpm
owncloud-client-nautilus-2.10.1-1.el8.x86_64.rpm
owncloud-client-nemo-2.10.1-1.el8.x86_64.rpm
Ce répertoire contient également tous les logs de construction :
Installation locale
Pour installer ces paquets localement, utilisez dnf avec l'option
localinstall plutôt que la commande de bas niveau rpm -ivh. Cette manière de procéder
facilitera de façon significative la gestion des dépendances :
Pour aller plus loin
Dans notre prochain article, nous nous intéresserons de plus près à la mise en place d'un dépôt de paquets personnalisé dans le but de pouvoir installer les paquets RPM construits par nos propres soins sur un grand nombre de machines.
La rédaction de cette documentation demande du temps et des quantités significatives de café espresso. Vous appréciez ce blog ? Offrez un café au rédacteur en cliquant sur la tasse.


