Next: , Previous: , Up: Interfaz programática   [Contents][Index]


8.6 Fases de construcción

Prácticamente todos los sistemas de construcción de paquetes implementan una noción de fases de construcción: una secuencia de acciones ejecutadas por el sistema de construcción, cuando usted construya el paquete, que conducen a la instalación de su producción en el almacén. Una excepción notable es el sistema de construcción trivial trivial-build-system (see Sistemas de construcción).

As discussed in the previous section, those build systems provide a standard list of phases. For gnu-build-system, the main build phases are the following:

set-paths

Define search path environment variables for all the input packages, including PATH (see Search Paths).

unpack

Extrae el archivador tar de la fuente, y cambia el directorio actual al directorio recién extraído. Si la fuente es realmente un directorio, lo copia al árbol de construcción y entra en ese directorio.

patch-source-shebangs

Sustituye secuencias “#!” encontradas al inicio de los archivos de fuentes para que hagan referencia a los nombres correctos de archivos del almacén. Por ejemplo, esto cambia #!/bin/sh por #!/gnu/store/…-bash-4.3/bin/sh.

configure

Ejecuta el guión configure con algunas opciones predeterminadas, como --prefix=/gnu/store/…, así como las opciones especificadas por el parámetro #:configure-flags.

build

Ejecuta make con la lista de opciones especificadas en #:make-flags. Si el parámetro #:parallel-build? es verdadero (por defecto), construye con make -j.

check

Ejecuta make check, u otro objetivo especificado con #:test-target, a menos que se pasase #:tests? #f. Si el parámetro #:parallel-tests? es verdadero (por defecto), ejecuta make check -j.

install

Ejecuta make install con las opciones enumeradas en #:make-flags.

patch-shebangs

Sustituye las secuencias “#!” en los archivos ejecutables instalados.

strip

Extrae los símbolos de depuración de archivos ELF (a menos que el valor de #:strip-binaries? sea falso), y los copia a la salida debug cuando esté disponible (see Instalación de archivos de depuración).

validate-runpath

Validate the RUNPATH of ELF binaries, unless #:validate-runpath? is false (see Sistemas de construcción).

This validation step consists in making sure that all the shared libraries needed by an ELF binary, which are listed as DT_NEEDED entries in its PT_DYNAMIC segment, appear in the DT_RUNPATH entry of that binary. In other words, it ensures that running or using those binaries will not result in a “file not found” error at run time. See -rpath in The GNU Linker, for more information on RUNPATH.

Other build systems have similar phases, with some variations. For example, cmake-build-system has same-named phases but its configure phases runs cmake instead of ./configure. Others, such as python-build-system, have a wholly different list of standard phases. All this code runs on the build side: it is evaluated when you actually build the package, in a dedicated build process spawned by the build daemon (see Invocación de guix-daemon).

Las fases de construcción se representan como listas asociativas o “alists” (see Association Lists in GNU Guile Reference Manual) donde cada clave es un símbolo que nombra a la fase y el valor asociado es un procedimiento que acepta un número arbitrario de parámetros. Por convención, estos procedimientos reciben información sobre la construcción en forma de parámetros que usan palabras clave, de los cuales pueden hacer uso o ignorarlos.

Por ejemplo, esta es la forma en la que (guix build gnu-build-system) define %standard-phases, la variable que contiene su lista asociativa de fases de construcción23:

;; Las fases de construcción de 'gnu-build-system'.

(define* (unpack #:key source #:allow-other-keys)
  ;; Extracción del archivador tar de las fuentes.
  (invoke "tar" "xvf" source))

(define* (configure #:key outputs #:allow-other-keys)
  ;; Ejecución del guión 'configure'. Instalación de la salida
  ;; en "out".
  (let ((out (assoc-ref outputs "out")))
    (invoke "./configure"
            (string-append "--prefix=" out))))

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

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

(define* (install #:allow-other-keys)
  ;; Instalación de los archivos en el prefijo especificado
  ;; al guión 'configure'.
  (invoke "make" "install"))

(define %standard-phases
  ;; La lista de las fases estándar (algunas se omiten por
  ;; brevedad). Cada elemento es un par símbolo/procedimiento.
  (list (cons 'unpack unpack)
        (cons 'configure configure)
        (cons 'build build)
        (cons 'check check)
        (cons 'install install)))

Aquí se muestra como %standard-phases se define como una lista de pares símbolo/procedimiento (see Pairs in GNU Guile Reference Manual). El primer par asocia el procedimiento unpack con el símbolo unpack—un nombre; el segundo par define de manera similar la fase configure, etcétera. Cuando se construye un paquete que usa gnu-build-system, con su lista predeterminada de fases, estas fases se ejecutan de manera secuencial. Puede ver el nombre de cada fase a su inicio y tras su finalización en el registro de construcción de los paquetes que construya.

Echemos un vistazo a los propios procedimientos. Cada uno se define con define*: #:key enumera parámetros con palabras clave que el procedimiento acepta, con la posibilidad de proporcionar un valor predeterminado, y #:allow-other-keys especifica que se ignora cualquier otra palabra clave en los parámetros (see Optional Arguments in GNU Guile Reference Manual).

El procedimiento unpack utiliza el valor proporcionado al parámetro source, usado por el sistema de construcción usa para proporcionar el nombre de archivo del archivador de fuentes (o la copia de trabajo del sistema de control de versiones), e ignora otros parámetros. La fase configure únicamente tiene en cuenta el parámetro outputs, una lista asociativa de nombres de salida de paquetes con su nombre de archivo en el almacén (see Paquetes con múltiples salidas). Para ello se extrae el nombre de archivo de out, la salida predeterminada, y se lo proporciona a la orden ./configure como el prefijo de la instalación (./configure --prefix=out), lo que significa que make install acabará copiando todos los archivos en dicho directorio (see configuration and makefile conventions in GNU Coding Standards). Tanto build como install ignoran todos los parámetros. check utiliza el parámetro test-target, que especifica el nombre del objetivo del archivo Makefile que debe ejecutarse para ejecutar las pruebas; se imprime un mensaje y se omiten las pruebas cuando el parámetro tests? tiene falso como valor.

Se puede cambiar con el parámetro #:phases la lista de fases usada por el sistema de construcción para un paquete en particular. El cambio del conjunto de fases de construcción se realiza mediante la construcción de una nueva lista asociativa basada en la lista asociativa %standard-phases descrita previamente. Esto se puede llevar a cabo con procedimientos estándar para la manipulación de listas asociativas como alist-delete (see SRFI-1 Association Lists in GNU Guile Reference Manual); no obstante es más conveniente hacerlo con modify-phases (see modify-phases).

Aquí se encuentra un ejemplo de una definición de paquete que borra la fase configure de %standard-phases e inserta una nueva fase antes de la fase build, llamada proporciona-prefijo-en-makefile:

(define-public example
  (package
    (name "example")
    ;; other fields omitted
    (build-system gnu-build-system)
    (arguments
     (list
      #:phases
      #~(modify-phases %standard-phases
          (delete 'configure)
          (add-before 'build 'set-prefix-in-makefile
            (lambda* (#:key inputs #:allow-other-keys)
              ;; Modify the makefile so that its
              ;; 'PREFIX' variable points to #$output and
              ;; 'XMLLINT' points to the correct path.
              (substitute* "Makefile"
                (("PREFIX =.*")
                 (string-append "PREFIX = " #$output "\n"))
                (("XMLLINT =.*")
                 (string-append "XMLLINT = "
                                (search-input-file inputs "/bin/xmllint")
                                "\n"))))))))))

The new phase that is inserted is written as an anonymous procedure, introduced with lambda*; it looks for the xmllint executable under a /bin directory among the package’s inputs (see Referencia de package). It also honors the outputs parameter we have seen before. See Utilidades de construcción, for more about the helpers used by this phase, and for more examples of modify-phases.

Tip: You can inspect the code associated with a package’s #:phases argument interactively, at the REPL (see Using Guix Interactively).

Keep in mind that build phases are code evaluated at the time the package is actually built. This explains why the whole modify-phases expression above is quoted (it comes after the #~ or hash-tilde): it is staged for later execution. See Expresiones-G, for an explanation of code staging and the code strata involved.


Footnotes

(23)

Presentamos una visión simplificada de las fases de dichas construcción, ¡eche un vistazo al módulo (guix build gnu-build-system) para ver todos los detalles!


Next: Utilidades de construcción, Previous: Sistemas de construcción, Up: Interfaz programática   [Contents][Index]