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


8.5 Phases de construction

Presque tous les systèmes de construction de paquets mettent en œuvre une notion de phase de construction : une séquence d’actions que le système de construction exécute, lorsque vous construisez le paquet, conduisant aux sous-produits installés dans le dépôt. Une exception notable est le trivial-build-system (voir Systèmes de construction) minimaliste.

Comme nous l’avons vu dans la section précédente, ces systèmes de construction fournissent une liste standard de phases. Pour gnu-build-system, les phases standard comprennent une phase unpack pour décompresser l’archive du code source, une phase configure pour exécuter ./configure, une phase build pour exécuter make, et (entre autres) une phase install pour exécuter make install ; voir Systèmes de construction, pour une vue plus détaillée de ces phases. De même, cmake-build-system hérite de ces phases, mais sa phase configure exécute cmake au lieu de ./configure. D’autres systèmes de compilation, tels que python-build-system, ont une liste de phases standard totalement différente. Tout ce code s’exécute côté construction : il est évalué lorsque vous construisez réellement le paquet, dans un processus de construction dédié engendré par le démon de construction (voir Invoquer guix-daemon).

Les phases de construction sont représentées sous forme de listes d’associations ou « alists » (voir Listes d’association dans Manuel de référence de GNU Guile) où chaque clé est un symbole pour le nom de la phase et la valeur associée est une procédure qui accepte un nombre arbitraire d’arguments. Par convention, ces procédures reçoivent des informations sur la construction sous la forme de paramètres nommés, qu’elles peuvent utiliser ou ignorer.

Par exemple, voici comment (guix build gnu-build-system) définit %standard-phases, la variable contenant sa liste de phases de construction17 :

;; Les phases de construction de "gnu-build-system".

(define* (unpack #:key source #:allow-other-keys)
  ;; Extrait l'archive des sources.
  (invoke "tar" "xvf" source))

(define* (configure #:key outputs #:allow-other-keys)
  ;; Exécute le script « configure ». Installe la sortie « out ».
  (let ((out (assoc-ref outputs "out")))
    (invoke "./configure"
            (string-append "--prefix=" out))))

(define* (build #:allow-other-keys)
  ;; Compile.
  (invoke "make"))

(define* (check #:key (test-target "check") (tests? #true)
                #:allow-other-keys)
  ;; Lance la suite de tests.
  (if tests?
      (invoke "make" test-target)
      (display "test suite not run\n")))

(define* (install #:allow-other-keys)
  ;; Installe les fichiers sous le préfixe spécifié à « configure ».
  (invoke "make" "install"))

(define %standard-phases
  ;; La liste des phases standard (un certain nombre d'entre elles sont omises
  ;; par souci de concision).  Chaque élément est une paire symbole/procédure.
  (list (cons 'unpack unpack)
        (cons 'configure configure)
        (cons 'build build)
        (cons 'check check)
        (cons 'install install)))

Cela montre comment %standard-phases est défini comme une liste de paires symbole/procédure (voir Pairs dans GNU Guile Reference Manual). La première paire associe le symbole unpack — un nom — à la procédure unpack ; la deuxième paire définit la phase configure de manière similaire, et ainsi de suite. Lors de la construction d’un paquet qui utilise gnu-build-system avec sa liste de phases par défaut, ces phases sont exécutées de manière séquentielle. Vous pouvez voir le nom de chaque phase commencée et terminée dans le journal de construction des paquets que vous construisez.

Examinons maintenant les procédures elles-mêmes. Chacune est définie par define* : #:key énumère les paramètres nommés que la procédure accepte, éventuellement avec une valeur par défaut, et #:allow-other-keys précise que les autres paramètres nommés sont ignorés (voir Optional Arguments dans GNU Guile Reference Manual).

La procédure unpack respecte le paramètre source, que le système de compilation utilise pour passer le nom de fichier de l’archive source (ou le répertoire cloné d’un système de contrôle de version), et elle ignore les autres paramètres. La phase configure ne s’intéresse qu’au paramètre outputs, une liste d’association des noms des sorties du paquet avec le nom de leur fichier du dépôt (voir Des paquets avec plusieurs résultats). Elle extrait le nom de fichier de out, la sortie par défaut, et le transmet à ./configure comme préfixe d’installation, ce qui signifie que make install copiera tous les fichiers vers ce répertoire (voir configuration and makefile conventions dans GNU Coding Standards). build et install ignorent tous leurs arguments. check prend en considération l’argument test-target, qui spécifie le nom de la cible du Makefile pour exécuter les tests ; il imprime un message et saute les tests lorsque tests? est faux.

La liste des phases utilisées pour un paquet particulier peut être modifiée avec le paramètre #:phases du système de construction. La modification de l’ensemble des phases de construction se résume à la création d’une nouvelle liste de phases basée sur la liste %standard-phases décrite ci-dessus. On peut faire cela à l’aide des procédures standards qui manipulent des listes d’associations telles que alist-delete (voir SRFI-1 Association Lists dans GNU Guile Reference Manual) ; cependant, il est plus pratique de le faire avec modify-phases (voir modify-phases).

Voici un exemple de définition de paquet qui supprime la phase configure de %standard-phases et insère une nouvelle phase avant la phase build, appelée set-prefix-in-makefile :

(define-public example
  (package
    (name "example")
    ;; les autres champs sont omis
    (build-system gnu-build-system)
    (arguments
     '(#:phases (modify-phases %standard-phases
                  (delete 'configure)
                  (add-before 'build 'set-prefix-in-makefile
                    (lambda* (#:key outputs #:allow-other-keys)
                      ;; Modifie le Makefile pour que sa variable
                      ;; 'PREFIX' pointe vers « out ».
                      (let ((out (assoc-ref outputs "out")))
                        (substitute* "Makefile"
                          (("PREFIX =.*")
                           (string-append "PREFIX = "
                                          out "\n")))
                        #true))))))))

La nouvelle phase insérée est écrite comme une procédure anonyme, introduite avec lambda* ; elle honore le paramètre outputs que nous avons vu auparavant. Voir Utilitaires de construction, pour en savoir plus sur les procédures auxiliaires utilisées par cette phase, et pour d’autres exemples de modify-phases.

Gardez à l’esprit que le code des phases de construction est évalué à la construction effective des paquets. Cela explique pourquoi toute l’expression modify-phases ci-dessus est citée (elle vient après ' ou apostrophe) : elle est mise de côté pour une exécution ultérieure. Voir G-Expressions, pour une explication de la mise en place du code et des strates de code concernées.


Notes de bas de page

(17)

Nous présentons une vue simplifiée de ces phases de construction, mais jetez un oeil à (guix build gnu-build-system) pour voir tous les détails !


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