Next: Search Paths, Previous: Fases de construcción, Up: Interfaz programática [Contents][Index]
En cuanto empiece a escribir definiciones de paquete no-triviales
(see Definición de paquetes) u otras acciones de construcción
(see 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)
(see 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
(see Using Guile Modules in 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)
.
Esta sección documenta procedimientos para el manejo de nombres de archivo del almacén.
Devuelve el nombre del directorio del almacén.
Devuelve verdadero si archivo está en el almacén.
Elimina /gnu/store y el hash de archivo, un nombre de archivo
del almacén. El resultado es habitualmente una cadena
"paquete-versión"
.
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.
Los siguientes procedimientos tratan con archivos y tipos de archivos.
Devuelve #t
si dir existe y es un directorio.
Devuelve #t
si archivo existe y es ejecutable.
Devuelve #t
si archivo es enlace simbólico (“symlink”).
Devuelve #t
si archivo es, respectivamente, un archivo ELF, un
archivador ar
(como una biblioteca estática .a), o un archivo
comprimido con gzip.
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.
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 (see POSIX in GNU Guile Reference Manual).
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
(see Processes in 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.
Crea el directorio dir y todos sus predecesores.
Crea directorio si no existe y copia archivo allí con el mismo nombre.
Activa el permiso de escritura en archivo para su propietaria.
copy-file] [#:keep-mtime? #f] [#:keep-permissions? #t] [#:select? (const
#t)] Copy source directory to destination. Follow symlinks if
follow-symlinks? is true; otherwise, just preserve them. Call
copy-file to copy regular files. Call select?, taking two
arguments, file and stat, for each entry in source, where
file is the entry’s absolute file name and stat is the result of
lstat
(or stat
if follow-symlinks? is true); exclude
entries for which select? does not return true. When
keep-mtime? is true, keep the modification time of the files in
source on those of destination. When keep-permissions? is
true, preserve file permissions. Write verbose output to the log
port.
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.
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.
Be careful about using $
to match the end of a line; by itself it
won’t match the terminating newline of a line. For example, to match a
whole line ending with a backslash, one needs a regex like
"(.*)\\\\\n$"
.
Esta sección documenta procedimientos de búsqueda y filtrado de archivos.
Devuelve un predicado que devuelve un valor verdadero cuando el nombre del archivo proporcionado sin la parte del directorio corresponde con expreg.
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" …)
Devuelve el nombre de archivo completo para programa tal y como se
encuentra en $PATH
, o #f
si no se ha encontrado
programa.
Return the complete file name for name as found in inputs;
search-input-file
searches for a regular file and
search-input-directory
searches for a directory. If name could
not be found, an exception is raised.
Here, inputs must be an association list like inputs
and
native-inputs
as available to build phases (see Fases de construcción).
Here is a (simplified) example of how search-input-file
is used in a
build phase of the wireguard-tools
package:
(add-after 'install 'wrap-wg-quick
(lambda* (#:key inputs outputs #:allow-other-keys)
(let ((coreutils (string-append (assoc-ref inputs "coreutils")
"/bin")))
(wrap-program (search-input-file outputs "bin/wg-quick")
#:sh (search-input-file inputs "bin/bash")
`("PATH" ":" prefix ,(list coreutils))))))
You’ll find handy procedures to spawn processes in this module, essentially
convenient wrappers around Guile’s system*
(see system*
in GNU Guile Reference Manual).
Invoke program with the given args. Raise an
&invoke-error
exception if the exit code is non-zero; otherwise
return #t
.
The advantage compared to system*
is that you do not need to check
the return value. This reduces boilerplate in shell-script-like snippets
for instance in package build phases.
Return true if c is an &invoke-error
condition.
Access specific fields of c, an &invoke-error
condition.
Report to port (by default the current error port) about c, an
&invoke-error
condition, in a human-friendly way.
Typical usage would look like this:
(use-modules (srfi srfi-34) ;for 'guard' (guix build utils)) (guard (c ((invoke-error? c) (report-invoke-error c))) (invoke "date" "--imaginary-option")) -| command "date" "--imaginary-option" failed with status 1
Invoke program with args and capture program’s standard
output and standard error. If program succeeds, print nothing and
return the unspecified value; otherwise, raise a &message
error
condition that includes the status code and the output of program.
Here’s an example:
(use-modules (srfi srfi-34) ;for 'guard' (srfi srfi-35) ;for 'message-condition?' (guix build utils)) (guard (c ((message-condition? c) (display (condition-message c)))) (invoke/quiet "date") ;all is fine (invoke/quiet "date" "--imaginary-option")) -| 'date --imaginary-option' exited with status 1; output follows: date: unrecognized option '--imaginary-option' Try 'date --help' for more information.
(guix build utils)
también contiene herramientas para la manipulación
de las fases de construcción usadas por los sistemas de construcción
(see Sistemas de construcción). 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 (see 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.
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 (see Optional
Arguments in 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
;; Patch 'egrep' and 'fgrep' to execute 'grep' via its
;; absolute file name instead of searching for it in $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")))))))
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 'configure' script
(replace 'install
(lambda* (#:key outputs #:allow-other-keys)
;; The package's Makefile doesn't provide an "install"
;; rule so do it by ourselves.
(let ((bin (string-append (assoc-ref outputs "out")
"/bin")))
(install-file "footswitch" bin)
(install-file "scythe" bin)))))
It is not unusual for a command to require certain environment variables to be set for proper functioning, typically search paths (see Search Paths). Failing to do that, the command might fail to find files or other commands it relies on, or it might pick the “wrong” ones—depending on the environment in which it runs. Examples include:
PATH
;
GUILE_LOAD_PATH
and GUILE_LOAD_COMPILED_PATH
;
QT_PLUGIN_PATH
.
For a package writer, the goal is to make sure commands always work the same
rather than depend on some external settings. One way to achieve that is to
wrap commands in a thin script that sets those environment variables,
thereby ensuring that those run-time dependencies are always found. The
wrapper would be used to set PATH
, GUILE_LOAD_PATH
, or
QT_PLUGIN_PATH
in the examples above.
To ease that task, the (guix build utils)
module provides a couple of
helpers to wrap commands.
Make a wrapper for program. variables should look like this:
'(variable delimiter position list-of-directories)
where delimiter is optional. :
will be used if delimiter
is not given.
For example, this call:
(wrap-program "foo"
'("PATH" ":" = ("/gnu/.../bar/bin"))
'("CERT_PATH" suffix ("/gnu/.../baz/certs"
"/qux/certs")))
will copy foo to .foo-real and create the file foo with the following contents:
#!location/of/bin/bash export PATH="/gnu/.../bar/bin" export CERT_PATH="$CERT_PATH${CERT_PATH:+:}/gnu/.../baz/certs:/qux/certs" exec -a $0 location/of/.foo-real "$@"
If program has previously been wrapped by wrap-program
, the
wrapper is extended with definitions for variables. If it is not,
sh will be used as the interpreter.
Wrap the script program such that variables are set first. The
format of variables is the same as in the wrap-program
procedure. This procedure differs from wrap-program
in that it does
not create a separate shell script. Instead, program is modified
directly by prepending a Guile script, which is interpreted as a comment in
the script’s language.
Special encoding comments as supported by Python are recreated on the second line.
Note that this procedure can only be used once per file as Guile scripts are not supported.
Next: Search Paths, Previous: Fases de construcción, Up: Interfaz programática [Contents][Index]