Siguiente: , Anterior: , Subir: Interfaz programática   [Índice general][Índice]


8.6 Utilidades de construcción

En cuanto empiece a escribir definiciones de paquete no-triviales (véase Definición de paquetes) u otras acciones de construcción (véase Expresiones-G), es probable que empiece a buscar funciones auxiliares parecidas a las habituales en el intérprete de ordenes—creación de directorios, borrado y copia recursiva de archivos, manipulación de fases de construcción, etcétera. El módulo (guix build utils) proporciona dichos procedimientos auxiliares.

La mayoría de sistemas de construcción cargan (guix build utils) (véase Sistemas de construcción). Por tanto, cuando construya fases de construcción personalizadas para sus definiciones de paquetes, habitualmente puede asumir que dichos procedimientos ya han sido incorporados al ámbito de ejecución.

Cuando escriba G-expressions, puede importar (guix build utils) en el “lado de la construcción” mediante el uso with-imported-modules e importandolos al ámbito actual con la forma sintáctica use-modules (véase Using Guile Modules en GNU Guile Reference Manual):

(with-imported-modules '((guix build utils))  ; Se importa.
  (computed-file "empty-tree"
                 #~(begin
                     ;; Se añade al ámbito actual.
                     (use-modules (guix build utils))

                     ;; Se usa su procedimiento 'mkdir-p'.
                     (mkdir-p (string-append #$output "/a/b/c")))))

El resto de esta sección es la referencia de la mayoría de las procedimientos de utilidad proporcionados por (guix build utils).

8.6.1 Tratamiento de nombres de archivo del almacén

Esta sección documenta procedimientos para el manejo de nombres de archivo del almacén.

Procedimiento Scheme: %store-directory

Devuelve el nombre del directorio del almacén.

Procedimiento Scheme: store-file-name? archivo

Devuelve verdadero si archivo está en el almacén.

Procedimiento Scheme: strip-store-file-name archivo

Elimina /gnu/store y el hash de archivo, un nombre de archivo del almacén. El resultado es habitualmente una cadena "paquete-versión".

Procedimiento Scheme: package-name>name+version nombre

Cuando se proporciona nombre, un nombre de paquete como "foo-0.9.1b", devuelve dos valores: "foo" y "0.9.1b". Cuando la perte de la versión no está disponible, se devuelve nombre y #f. Se considera que el primer guión seguido de un dígito introduce la parte de la versión.

8.6.2 Tipos de archivo

Los siguientes procedimientos tratan con archivos y tipos de archivos.

Procedimiento Scheme: directory-exists? dir

Devuelve #t si dir existe y es un directorio.

Procedimiento Scheme: executable-file archivo

Devuelve #t si archivo existe y es ejecutable.

Devuelve #t si archivo es enlace simbólico (“symlink”).

Procedimiento Scheme: elf-file? archivo
Procedimiento Scheme: ar-file? archivo
Procedimiento Scheme: gzip-file? archivo

Devuelve #t si archivo es, respectivamente, un archivo ELF, un archivador ar (como una biblioteca estática .a), o un archivo comprimido con gzip.

Procedimiento Scheme: reset-gzip-timestamp archivo [#:keep-mtime? #t]

Si archivo es un archivo gzip, reinicia su marca de tiempo embebida (como con gzip --no-name) y devuelve un valor verdadero. En otro caso devuelve #f. Cuando keep-mtime? es verdadero, se preserva el tiempo de modificación del archivo.

8.6.3 Manipulación de archivos

Los siguientes procedimientos y macros sirven de ayuda en la creación, modificación y borrado de archivos. Proporcionan funcionalidades comparables con las herrambientas comunes del intérprete de órdenes como mkdir -p, cp -r, rm -r y sed. Sirven de complemento a la interfaz de sistema de archivos de Guile, la cual es extensa pero de bajo nivel (véase POSIX en GNU Guile Reference Manual).

Sintaxis Scheme: with-directory-excursion directorio cuerpo

Ejecuta cuerpo con directorio como el directorio actual del proceso.

Esecialmente este macro cambia el directorio actual a directorio antes de evaluar cuerpo, usando chdir (véase Processes en GNU Guile Reference Manual). Se vuelve al directorio inicial en cuanto se abandone el ámbito dinámico de cuerpo, ya sea a través de su finalización normal o de una salida no-local como pueda ser una excepción.

Procedimiento Scheme: mkdir-p dir

Crea el directorio dir y todos sus predecesores.

Procedimiento Scheme: install-file archivo directorio

Crea directorio si no existe y copia archivo allí con el mismo nombre.

Procedimiento Scheme: make-file-writable archivo

Activa el permiso de escritura en archivo para su propietaria.

Procedimiento Scheme: copy-recursively fuente destino [#:log (current-output-port)] [#:follow-symlinks? #f] [#:keep-mtime? #f]

Copia el directorio fuente en destino. Sigue los enlaces simbólicos si follow-symlinks? es verdadero; en otro caso se preservan. Cuando keep-mtime? es verdadero se mantiene el tiempo de modificación de los archivos en fuente en aquellos copiados a destino. Muestra información detallada en el puerto log.

Procedimiento Scheme: delete-file-recursively dir [#:follow-mounts? #f]

Borra dir recursivamente, como rm -rf, sin seguir los enlaces simbólicos. No atraviesa puntos de montaje tampoco, a no ser que follow-mounts? sea verdadero. Informa de los errores, pero no devuelve error por ellos.

Sintaxis Scheme: substitute archivo ((expreg var-encontrada…) cuerpo…) …

Sustituye expreg en archivo con la cadena que devuelve cuerpo. La evaluación de cuerpo se realiza con cada var-encontrada asociada con la subexpresión posicional correspondiente de la expresión regular. Por ejemplo:

(substitute* archivo
  (("hola")
   "buenos días\n")
  (("algo([a-z]+)otro(.*)$" todo letras fin)
   (string-append "cosa" letras fin)))

En este ejemplo, cada ver que una línea de archivo contiene hola, esto se sustituye por buenos días. Cada vez que una línea del archivo corresponde con la segunda expresión regular, todo se asocia con la cadena encontrada al completo, letras toma el valor de la primera sub-expresión, y fin se asocia con la última.

Cuando una de las var-encontrada es _, no se asocia ninguna variable con la correspondiente subcadena.

También puede proporcionarse una lista como archivo, en cuyo caso los nombres de archivo que contenga serán los que se sometan a las sustituciones.

Tenga cuidado con el uso de $ para marcar el final de una línea; la cadena encontrada no contiene el caracter de salto de línea al final.

8.6.4 Búsqueda de archivos

Esta sección documenta procedimientos de búsqueda y filtrado de archivos.

Procedimiento Scheme: file-name-predicate expreg

Devuelve un predicado que devuelve un valor verdadero cuando el nombre del archivo proporcionado sin la parte del directorio corresponde con expreg.

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

Devuelve una lista ordenada lexicográficamente de los archivos que se encuentran en dir para los cuales pred devuelve verdadero. Se le proporcionan dos parámetros a pred: la ruta absoluta del archivo y su búfer de stat; el predicado predeteminado siempre devuelve verdadero. pred también puede ser una expresión regular, en cuyo caso es equivalente a escribir (file-name-predicate pred). stat se usa para obtener información del archivo; el uso de lstat significa que no se siguen los enlaces simbólicos. Si directories? es verdadero se incluyen también los directorios. Si fail-on-error? es verdadero, se emite una excepción en caso de error.

Aquí se pueden encontrar algunos ejemplos en los que se asume que el directorio actual es la raíz del arbol de fuentes de Guix:

;; Enumera todos los archivos regulares en el directorio actual.
(find-files ".")
 ("./.dir-locals.el" "./.gitignore" )

;; Enumera todos los archivos .scm en gnu/services.
(find-files "gnu/services" "\\.scm$")
 ("gnu/services/admin.scm" "gnu/services/audio.scm" )

;; Enumera los archivos ar en el directorio actual.
(find-files "." (lambda (file stat) (ar-file? file)))
 ("./libformat.a" "./libstore.a" )
Procedimiento Scheme: which programa

Devuelve el nombre de archivo completo para programa tal y como se encuentra en $PATH, o #f si no se ha encontrado programa.

8.6.5 Fases de construcción

(guix build utils) también contiene herramientas para la manipulación de las fases de construcción usadas por los sistemas de construcción (véase Sistemas de construcción). Las fases de construcción se representan como listas asociativas o “alists” (véase Association Lists en GNU Guile Reference Manual) donde cada clave es un símbolo que nombra a la fase, y el valor asociado es un procedimiento (véase Fases de construcción).

Tanto el propio Guile como el módulo (srfi srfi-1) proporcionan herramientas para la manipulación de listas asociativas. El módulo (guix build utils) complementa estas con herramientas pensadas para las fases de construcción.

Sintaxis Scheme: modify-phases fases cláusula

Modifica fases de manera secuencial com cada indique cada cláusula, que puede tener una de las siguentes formas:

(delete nombre-fase)
(replace nombre-fase nueva-fase)
(add-before nombre-fase nombre-nueva-fase nueva-fase)
(add-after nombre-fase nombre-nueva-fase nueva-fase)

Donde cada nombre-fase y nombre-nueva-fase es una expresión que evalúa aun símbolo, y nueva-fase es una expresión que evalúa a un procedimiento.

El siguiente ejemplo se ha tomado de la definición del paquete grep. Añade una fase que se ejecuta tras la fase install, llamada fix-egrep-and-fgrep. Dicha fase es un procedimiento (lambda* genera procedimientos anónimos) que toma un parámetro de palabra clave #:outputs e ignora el resto (véase Optional Arguments en GNU Guile Reference Manual para obtener más información sobre lambda* y los parámetros opcionales y de palabras clave). La fase usa substitute* para modificar los guiones egrep y fgrep instalados para que hagan referencia a grep con su ruta de archivo absoluta:

(modify-phases %standard-phases
  (add-after 'install 'fix-egrep-and-fgrep
    ;; Modificamos 'egrep' y 'fgrep' para que ejecuten 'grep' a
    ;; través de la ruta absoluta de su archivo en vez de buscar
    ;; dicho binario en la variable de entorno $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))))

En el siguiente ejemplo se modifican las fases de dos maneras: se elimina la fase estándar configure, posiblemente porque el paquete no tiene un guión configure ni nada similar, y la fase install predeterminada se sustituye por una que copia manualmente el archivo ejecutable que se debe instalar:

(modify-phases %standard-phases
  (delete 'configure)      ;no hay guión 'configure'
  (replace 'install
    (lambda* (#:key outputs #:allow-other-keys)
      ;; El Makefile del paquete no tiene un objetivo
      ;; doesn't provide an "install", así que lo
      ;; hacemos a mano.
      (let ((bin (string-append (assoc-ref outputs "out")
                                "/bin")))
        (install-file "footswitch" bin)
        (install-file "scythe" bin)
        #t))))

Siguiente: , Anterior: , Subir: Interfaz programática   [Índice general][Índice]