Dans un précédent article nous avons montré la base concernant la création de paquets avec RPM. Dans celui-ci nous abordons des sujets plus avancés.
Débloque les + belles offres tech en 10 mins
Les macros RPM
Dans le précédent article nous avons parlé de macros RPM. La bonne nouvelle est que vous pouvez créer vos propres macros ! Pour ce faire, commencez par créer un fichier dans le dossier /etc/rpm
nommé macro.xxx
, par exemple /etc/rpm/macros.foobar
.
Il existe deux types de macros :
- Les premières ressemblent fortement à des variables et ne sont en fait que des raccourcis vers d’autres chaînes de caractères. Elles tiennent sur une ligne.
- Les deuxièmes sont de véritables fonctions en shell, écrites en bash.
Dans les deux cas les macros peuvent réutiliser d’autres macros existantes.
Dernier point : pensez à packager vos macros et les mettre sous gestionnaire de version. Autrement personne ne pourra reconstruire vos paquets, ce serait dommage non ?
Maintenant voyons ça plus en détail.
Les macros pour la substitution de chaînes de caractères
Ces macros sont en fait très simples et ne prennent pas de paramètre. En fait elles sont très similaires aux variables que vous pourriez définir dans vos fichiers .spec, à ceci près que vous n’avez pas besoin de les faire précéder du symbole %global
.
Par exemple si vous voulez une macro pour définir les droits par défaut des utilisateurs sur les fichiers pour un autre compte que root vous écrirez :
%my_defattr %defattr(-,foo,bar,-)
De la même manière si vous voulez donner un répertoire de log commun à mettre dans la section %files de votre RPM, vous écrirez :
%my_logdir /foo/bar/log
Les macros avec du vrai code
Les macros avec du vrai code contiennent soit du bash, soit des appels à d’autres macros RPM, soit les deux. Il y a plusieurs trucs à savoir au moment de les écrire :
– Le nom de la macro doit se terminer par ()
.
– Les paramètres donnés au macros sont %1, %2, %n. J’avoue ne pas connaître la limite, je vous laisse tester, cela dit %9 me paraît un bon candidat pour le maximum.
– Toutes les lignes doivent se terminer par un backslash \
. Les lignes en shell doivent précéder ce backslash d’un point virgule.
– La fin de la macro doit se terminer par %{nil}
qui doit être tout seul sur sa ligne.
Voici un exemple pour indiquer que les fichiers de configuration appartiennent à un utilisateur donné :
%my_config_file() \
%attr(644,foo,bar) %1 \
%config(noreplace) %1 \
%{nil}
Cette macro fait en sorte que tous les fichiers de configuration qui l’utilisent appartiennent à l’utilisateur foo et le groupe bar, avec les droits 644, et d’autre part ces fichiers ne sont pas remplacés lors de la mise à jour d’un paquet. L’invocation de cette macro se passerait dans la section %files et serait de la forme :
%my_config_file /foo/bar
Voici un autre exemple avec du vrai code shell :
%my_hello() \
firstname=%1 ; \
lastname=%2 ; \
echo >&2 "Hello $firstname $lastname" ; \
mkdir -p %{buildroot}/$lastname/$firstname ; \
%{nil}
Cette macro serait invoquée à l’étape %install du build sous la forme :
%my_hello John Smith
Mise en place de mock pour créer des fichiers RPM
Mock est un outil qui permet de construire des RPMs de manière fiable et reproductible. Pour ce faire, il crée en fait un chroot dans lequel il va installer un système de base que vous pouvez spécifier dans vos fichiers de configuration du système. Cette section n’indique pas comment utiliser mock dans le détail, il y aurait de quoi en écrire des pages et on peut trouver des tutoriels, notamment là.
Installation de mock
L’outil mock se trouve dans le repo EPEL. Vous devez donc le déclarer comme indiqué ici. Ensuite, il faut taper la commande suivante :
yum install mock
L’étape suivante consiste à ajouter l’utilisateur avec lequel vous voulez construire les RPM au groupe mock
, puis le déconnecter et reconnecter pour que les modifications prennent effet.
Configuration de mock
La configuration de mock se trouve dans le dossier /etc/mock
. En fait dedans il y a trois fichiers qui nous intéressent, à savoir :
– defaults.cfg : déclaration d’options de configuration et des repos à partir desquels mock ira chercher ses fichiers. La syntaxe pour les options de configuration est config_opts['option'] = 'value'
. Quant à la syntaxe des repos c’est la même que celle que vous pourriez trouver dans /etc/yum.repos.d
– sites-defaults.cfg : déclaration d’options plus globales. defaults.cfg
sert pour définir les options pour une distribution cible donnée, alors que site-defaults.cfg
s’applique à tout le monde.
– logging.ini : les options du loggueur, classique quoi.
Vous trouverez des exemples pour config_opts ici.
Par défaut je déconseille vivement de modifier les fichiers à cet endroit car ils sont notamment utilisés si vous devez faire des paquets directement pour RedHat. Si vous devez faire des fichiers custom, faites le à un autre endroit différent. La seule option qu’il serait licite de modifier est config_opts['http_proxy']
dans site-defaults.cfg si vous êtes derrière un proxy.
Dans la suite on va considérer que vous avez créé votre configuration dans le dossier /foo/mock_config
.
Construction des paquets SRPM et RPM
Avant de construire un paquet RPM on passe généralement par un paquet source RPM à partir duquel vous pouvez reconstruire à volonté votre paquet. Le prérequis ici est que vous ayez bien vos archives de source ainsi que le fichier spec. Ensuite pour lancer mock, on exécute :
mock --spec <chemin_de_votre_fichier_spec> --sources <chemin_de_votre_archive_source> --configdir /foo/mock_config --resultdir /foo/srpm --buildsrpm
Si tout se passe bien vous aurez à cette étape un fichier SRPM sous le dossier /foo/srpm.
Ensuite, on va utiliser ce SRPM pour construire notre RPM. Ca se fait de la manière suivante :
mock --rebuild /foo/srpm/*.src.rpm --configdir /foo/mock_config --resultdir /foo/rpm
Et là si tout se passe bien vous aurez votre RPM dans le dossier /foo/rpm
.
Problèmes communs
Il arrive fréquemment que vous puissiez compiler vos programmes en local mais pas avec mock. La raison est en fait très simple : vous avez oublié de mentionner des BuildRequires
dans votre fichier SPEC de RPM. Il suffit de les ajouter et tout devrait rentrer dans l’ordre.
Un fichier SPEC qui décrit plusieurs RPM
Un truc qui peut arriver fréquemment est que vous ayez besoin de découper une archive de sources en plusieurs RPM. La solution pour ce faire est d’utiliser un fichier SPEC de RPM qui décrit plusieurs paquets. Mais comment est-ce posssssssiiiiiibbbbblllleeeeuuuuhhhh ???
En fait, un fichier définissant plusieurs paquets ressemble fortement à un fichier pour un seul paquet, à ceci près que chaque sous paquet a sa propre description, son propre Summary
et sa propre liste de fichiers. Les sections %prep
, %install
et %build
sont communes à tout le monde. Les sections %pre
, %post
, %preun
et %postun
sont par contre propres à chaque sous-paquet. Par ailleurs les noms des paquets enfants porteront celui du paquet parent. Par exemple si le nom global du spec file est foo
, et que vous avez un sous-paquet nommé bar
, le nom résultant du sous-paquet sera foo-bar
.
Voyons un exemple :
Name: pckgtest
Version: 1.0
Release: 1%{?dist}
Summary: my dummy package
License: copyright Jobprod
URL: http://www.welovedevs.com
Source0: dummy.tar.gz
BuildRequires: cmake
BuildRequires: gcc
%description
Example parent package
%package foo
Summary: subpackage foo
%description foo
Subpackage foo description
%package bar
Summary: description bar
%description bar
Subpackage bar description
%prep
%setup -q -n
%build
%configure
make
%install
make install DESTDIR=%{buildroot}
%pre foo
echo >&2 "I am installing foo"
%postun foo
echo >&2 "I am uninstalling foo"
%files foo
%defattr(-,root,root,-)
/foo
/usr/bin/foo
%files bar
%defattr(-,root,root,-)
/bar
/usr/bin/bar
%files
%defattr(-,root,root,-)
/pckgtest
/usr/bin/pckgtest
En compilant ce fichier SPEC vous obtiendrez en fait trois paquets, pckgtest
, pckgtest-foo
et pckgtest-bar
. Comme vous pouvez le voir les fichiers sont séparés entre le paquet parent et ses deux sous-paquets.
Et comme vous pouvez le voir il suffit d’avoir une directive %package
pour chaque sous-paquet, et ensuite pour les sections propres à chaque sous-paquet il suffit d’indiquer à chaque fois le nom du paquet concerné.
Dernier point : si vous ne voulez pas avoir le préfixe du paquet parent dans votre sous paquet, utilisez la directive suivante :
%package -n foo
Notez le paramètre -n
.
Désactiver la gestion de dépendances automatique
Par défaut, au moment d’installer un RPM, celui-ci va rechercher automatiquement toutes les dépendances requises pour votre paquet en analysant par exemple les librairies de vos programmes C.
Cette fonction peut sauver la vie mais il ne faut pas se baser dessus pour gérer les dépendances. D’autre part des fois elle peut se vautrer lamentablement, empêchant l’installation de votre paquet. Ca arrive surtout avec certains logiciels propriétaires. Si vous êtes confronté à un tel cas, utilisez la directive suivante dans l’en-tête de votre paquet :
AutoReqProv: no
A noter que dans le cas d’un fichier SPEC contenant des sous-paquets, vous devrez le déclarer pour chaque sous-paquet.
A ne jamais faire
Même si cette fonctionnalité existe, ne faites jamais de RPM dits relogeables, c’est à dire des RPMs dans lequel vous pouvez changer le chemin d’installation de base. C’est complètement déconseillé dans les guidelines RedHat, et d’autre part vous vous couperiez de tous les outils du type yum
.
Pour conclure
Ceci n’est encore qu’un aperçu de ce qu’on peut faire avec RPM. Il existe d’autres ressources sur Internet dont la documentation Fedora et la documentation Max RPM, cette dernière étant un peu dépassée.
En espérant que ce petit billet vous aide tout de même… 😉
Débloque les + belles offres tech en 10 mins
Cet article vous a plu ? Vous aimerez sûrement aussi :
- Introduction à la création de paquets avec RPM
- La démarche devops
- L’intégration continue
- 2014 sera Javascript ou ne sera pas
Julien
Moi c’est Julien, ingénieur en informatique avec quelques années d’expérience. Je suis tombé dans la marmite étant petit, mon père avait acheté un Apple – avant même ma naissance (oui ça date !). Et maintenant je me passionne essentiellement pour tout ce qui est du monde Java et du système, les OS open source en particulier.
Au quotidien, je suis devops, bref je fais du dév, je discute avec les opérationnels, et je fais du conseil auprès des clients.