Suivant: , Précédent: , Monter: Interface de programmation   [Table des matières][Index]


8.6 Utilitaires de construction

Dès que vous commencerez à écrire des définitions de paquets non triviales (voir Définition des paquets) ou d’autres actions de compilation (voir G-Expressions), vous commencerez probablement à chercher des fonctions auxiliaires pour les actions « de type shell » — créer des répertoires, copier et supprimer des fichiers de manière récursive, manipuler les phases de compilation, etc. Le module (guix build utils) fournit de telles procédures utilitaires.

La plupart des systèmes de construction chargent (guix build utils) (voir Systèmes de construction). Ainsi, lorsque vous écrivez des phases de construction personnalisées pour vos définitions de paquets, vous pouvez généralement supposer que ces procédures sont disponibles.

Lorsque vous écrivez des G-expressions, vous pouvez importer (guix build utils) « côté construction » en utilisant with-imported-modules et ensuite le rendre disponible avec la forme use-modules (voir Using Guile Modules dans GNU Guile Reference Manual) :

(with-imported-modules '((guix build utils))  ;on l'importe
  (computed-file "empty-tree"
                 #~(begin
                     ;; On le rend disponible.
                     (use-modules (guix build utils))

                     ;; On utilise sa procédure « mkdir-p » sans souci.
                     (mkdir-p (string-append #$output "/a/b/c")))))

Le reste de cette section est la référence pour la plupart des procédures auxiliaires fournies par (guix build utils).

8.6.1 Traitement des noms de fichiers du dépôt

Cette section documente les procédures de traitement des noms de fichier du dépôt.

Procédure Scheme : %store-directory

Renvoie le nom de répertoire du dépôt.

Procédure Scheme : store-file-name? fichier

Renvoie vrai si fichier est dans le dépôt.

Procédure Scheme : strip-store-file-name fichier

Enlevez le /gnu/store et le hash de fichier, un nom de fichier du dépôt. Le résultat est généralement une chaîne "paquet-version".

Procédure Scheme : package-name->name+version nom

Si l’on passe nom, un nom de paquet comme "foo-0.9.1b", on obtient deux valeurs : "foo" et "0.9.1b". Lorsque la partie version est indisponible, nom et #f sont renvoyés. Le premier trait d’union suivi d’un chiffre est considéré comme introduisant la partie version.

8.6.2 Types de fichier

Les procédures ci-dessous portent sur les fichiers et les types de fichiers.

Procédure Scheme : directory-exists? dir

Renvoie #t si dir existe et est un répertoire.

Procédure Scheme : executable-file? fichier

Renvoie #t si fichier existe et est exécutable.

Renvoie #t si fichier est un lien symbolique (un « symlink »).

Procédure Scheme : elf-file? fichier
Procédure Scheme : ar-file? fichier
Procédure Scheme : gzip-file? fichier

Renvoie #t si fichier est, respectivement, un fichier ELF, une archive ar (telle qu’une bibliothèque statique .a), ou un fichier gzip.

Procédure Scheme : reset-gzip-timestamp fichier [#:keep-mtime? #t]

Si fichier est un fichier gzip, réinitialise son horodatage intégré (comme avec gzip --no-name) et renvoie vrai. Sinon, renvoie #f. Lorsque keep-mtime? est vrai, conserve la date de modification de fichier.

8.6.3 Manipulation de fichiers

Les procédures et macros suivantes permettent de créer, modifier et supprimer des fichiers. Elles offrent des fonctionnalités comparables à celles des utilitaires shell courants tels que mkdir -p, cp -r, rm -r et sed. Elles complètent l’interface de système de fichiers étendue, mais de bas niveau, de Guile (voir POSIX dans GNU Guile Reference Manual).

Syntaxe Scheme : with-directory-excursion répertoire corps

Exécute corps avec répertoire comme répertoire actuel du processus.

En gros, cette macro change le répertoire actuel en répertoire avant d’évaluer corps, en utilisant chdir. (voir Processus dans Manuel de référence de GNU Guile). Elle revient au répertoire initial à la sortie de la portée dynamique de corps, qu’il s’agisse d’un retour de procédure normal ou d’une sortie non locale telle qu’une exception.

Procédure Scheme : mkdir-p dir

Crée le répertoire dir et tous ses ancètres.

Procédure Scheme : install-file fichier répertoire

Crée répertoire s’il n’existe pas et y copie fichier sous le même nom.

Procédure Scheme : make-file-writable fichier

Rend fichier inscriptible pour son propriétaire.

Procédure Scheme : copy-recursively source destination [#:log (current-output-port)] [#:follow-symlinks ? #f] [#:keep-mtime ? #f]

Copie le répertoire source dans destination. Suivez les liens symboliques si follow-symlinks? est vrai ; sinon, conservez-les. Lorsque keep-mtime? est vrai, conservez les heures de modification des fichiers dans source sur celles de destination. Écrivez une sortie verbeuse sur le port log.

Procédure Scheme : delete-file-recursively dir [#:follow-mounts? #f]

Efface récursivement dir, comme rm -rf, sans les liens symboliques suivants. Ne suit pas non plus les points de montage, à moins que follow-mounts? ne soit vrai. Rapporte mais ignore les erreurs.

Syntaxe Scheme : substitute* fichier ((regexp match-var…) body…) …

Remplace regexp dans fichier par la chaîne renvoyée par body. body est évalué avec chaque match-var lié à la sous-expression de regexp positionnelle correspondante. Par exemple :

(substitute* file
  (("hello")
   "good morning\n")
  (("foo([a-z]+)bar(.*)$" all letters end)
   (string-append "baz" letter end)))

Ici, chaque fois qu’une ligne de fichier contient hello, elle est remplacée par good morning. Chaque fois qu’une ligne de fichier correspond à la deuxième regexp, all est lié à la correspondance complète, letters est lié à la première sous-expression, et end est lié à la dernière.

Lorsque l’une des match-var est _, aucune variable n’est liée à la sous-chaîne de correspondance associée.

Autrement, fichier peut être une liste de noms de fichier, auquel cas ils sont tous sujets aux substitutions.

Faites attention à l’utilisation du $ pour faire correspondre la fin d’une ligne ; à lui seul, il ne correspondra pas à la fin d’une nouvelle ligne.

8.6.4 Recherche de fichiers

Cette section documente les procédures pour chercher et filtrer des fichiers.

Procédure Scheme : file-name-predicate regexp

Renvoie un prédicat qui devient vrai lorsqu’on lui passe un nom de fichier dont le nom de base correspond à regexp.

Procédure Scheme : find-files dir [pred] [#:stat lstat] [#:directories ? #f] [#:fail-on-error ? #f]

Renvoie la liste des fichiers triés lexicographiquement sous dir pour lesquels pred renvoie « vrai ». Deux arguments sont passés à pred : le nom absolu du fichier et son tampon stat ; le prédicat par défaut renvoie toujours « vrai ». pred peut également être une expression régulière, auquel cas elle est équivalente à (file-name-predicate pred). stat est utilisé pour obtenir des informations sur les fichiers ; l’utilisation de lstat signifie que les liens symboliques ne sont pas suivis. Si directories? est vrai, alors les répertoires seront également inclus. Si fail-on-error? est vrai, il lance une exception en cas d’erreur.

Voici quelques exemples où nous supposons que le répertoire actuel est la racine de l’arborescence des sources de Guix :

;; Liste tous les fichiers normaux dans le répertoire actuel.
(find-files ".")
 ("./.dir-locals.el" "./.gitignore" )

;; Liste tous les fichiers .scm sous gnu/services.
(find-files "gnu/services" "\\.scm$")
 ("gnu/services/admin.scm" "gnu/services/audio.scm" )

;; Liste les fichiers ar dans le répertoire actuel.
(find-files "." (lambda (file stat) (ar-file? file)))
 ("./libformat.a" "./libstore.a" )
Procédure Scheme : which programme

Renvoie le nom complet du fichier pour programme tel qu’il se trouve dans $PATH, ou #f si programme n’a pas pu être trouvé.

8.6.5 Phases de construction

Le (guix build utils) contient également des outils permettant de manipuler les phases de construction telles qu’elles sont utilisées par les systèmes de construction (voir Systèmes de construction). Les phases de construction sont représentées sous forme de listes d’associations ou « alists » (voir Association Lists dans Manuel de référence de GNU Guile) où chaque clé est un symbole désignant la phase et où la valeur associée est une procédure (voir Phases de construction).

Le noyau Guile et le module (srfi srfi-1) fournissent tous deux des outils pour manipuler les alignements. Le module (guix build utils) complète ces outils avec des outils écrits en tenant compte des phases de construction.

Syntaxe Scheme : modify-phases phases clause

Modifie phases séquentiellement selon chaque clause, qui peut avoir l’une des formes suivantes :

(delete old-phase-name)
(replace old-phase-name new-phase)
(add-before old-phase-name new-phase-name new-phase)
(add-after old-phase-name new-phase-name new-phase)

Où chaque phase-name ci-dessus est une expression s’évaluant en un symbole, et new-phase une expression évaluant à une procédure.

L’exemple ci-dessous est tiré de la définition du paquet grep. Il ajoute une phase à exécuter après la phase install, appelée fix-egrep-and-fgrep. Cette phase est une procédure (lambda* pour les procédures anonymes) qui prend un paramètre nommé #:outputs et ignore les paramètres nommés supplémentaires (voir Optional Arguments dans GNU Guile Reference Manual, pour en savoir plus sur lambda* et les arguments optionnels et nommés). La phase utilise substitute* pour modifier les scripts egrep et fgrep installés afin qu’ils se réfèrent à grep par son nom de fichier absolu :

(modify-phases %standard-phases
  (add-after 'install 'fix-egrep-and-fgrep
    ;; Corrige 'egrep' et 'fgrep' pour exécuter 'grep' via son
    ;; nom de fichier absolu au lieu de le chercher dans $PATH.
    (lambda* (#:key outputs #:allow-other-keys)
      (let* ((out (assoc-ref outputs "out"))
             (bin (string-append out "/bin")))
        (substitute* (list (string-append bin "/egrep")
                           (string-append bin "/fgrep"))
          (("^exec grep")
           (string-append "exec " bin "/grep")))
        #t))))

Dans l’exemple ci-dessous, les phases sont modifiées de deux façons : la phase standard configure est supprimée, vraisemblablement parce que le paquet n’a pas de script configure ou quelque chose de similaire, et la phase par défaut install est remplacée par une phase qui copie manuellement les fichiers exécutables à installer :

(modify-phases %standard-phases
  (delete 'configure)      ;no 'configure' script
  (replace 'install
    (lambda* (#:key outputs #:allow-other-keys)
      ;; Le Makefile du paquet ne fournit pas de règle « install »
      ;; alors on le fait nous-mêmes.
      (let ((bin (string-append (assoc-ref outputs "out")
                                "/bin")))
        (install-file "footswitch" bin)
        (install-file "scythe" bin)
        #t))))

Suivant: , Précédent: , Monter: Interface de programmation   [Table des matières][Index]