Nächste: guix repl
aufrufen, Vorige: Die Store-Monade, Nach oben: Programmierschnittstelle [Inhalt][Index]
Es gibt also „Ableitungen“, die eine Abfolge von Erstellungsaktionen
repräsentieren, die durchgeführt werden müssen, um ein Objekt im Store zu
erzeugen (siehe Ableitungen). Diese Erstellungsaktionen werden
durchgeführt, nachdem der Daemon gebeten wurde, die Ableitungen tatsächlich
zu erstellen; dann führt der Daemon sie in einer isolierten Umgebung (einem
sogenannten Container) aus (siehe Aufruf von guix-daemon
).
Wenig überraschend ist, dass wir diese Erstellungsaktionen gerne in Scheme
schreiben würden. Wenn wir das tun, bekommen wir zwei verschiedene
Schichten von Scheme-Code24: den
„wirtsseitigen Code“ („host code“) – also Code, der Pakete definiert,
mit dem Daemon kommuniziert etc. – und den „erstellungsseitigen Code“
(„build code“) – also Code, der die Erstellungsaktionen auch wirklich
umsetzt, indem Dateien erstellt werden, make
aufgerufen wird und
so weiter (siehe Erstellungsphasen).
Um eine Ableitung und ihre Erstellungsaktionen zu beschreiben, muss man
normalerweise erstellungsseitigen Code im wirtsseitigen Code einbetten. Das
bedeutet, man behandelt den erstellungsseitigen Code als Daten, was wegen
der Homoikonizität von Scheme – dass Code genauso als Daten
repräsentiert werden kann – sehr praktisch ist. Doch brauchen wir hier
mehr als nur den normalen Quasimaskierungsmechanismus mit quasiquote
in Scheme, wenn wir Erstellungsausdrücke konstruieren möchten.
Das Modul (guix gexp)
implementiert G-Ausdrücke, eine Form von
S-Ausdrücken, die zu Erstellungsausdrücken angepasst wurden. G-Ausdrücke
(englisch „G-expressions“, kurz Gexps) setzen sich grundlegend aus
drei syntaktischen Formen zusammen: gexp
, ungexp
und
ungexp-splicing
(alternativ einfach: #~
, #$
und
#$@
), die jeweils mit quasiquote
, unquote
und
unquote-splicing
vergleichbar sind (siehe quasiquote
in Referenzhandbuch zu GNU Guile). Es gibt aber
auch erhebliche Unterschiede:
Dieser Mechanismus ist nicht auf Pakete und Ableitung beschränkt: Es können
Compiler definiert werden, die weitere abstrakte, hochsprachliche
Objekte auf Ableitungen oder Dateien im Store „herunterbrechen“, womit diese
Objekte dann auch in G-Ausdrücken eingefügt werden können. Zum Beispiel sind
„dateiartige Objekte“ ein nützlicher Typ solcher abstrakter Objekte. Mit
ihnen können Dateien leicht in den Store eingefügt und von Ableitungen und
anderem referenziert werden (siehe unten local-file
und
plain-file
).
Zur Veranschaulichung dieser Idee soll uns dieses Beispiel eines G-Ausdrucks dienen:
(define build-exp
#~(begin
(mkdir #$output)
(chdir #$output)
(symlink (string-append #$coreutils "/bin/ls")
"list-files")))
Indem wir diesen G-Ausdruck an gexp->derivation
übergeben, bekommen
wir eine Ableitung, die ein Verzeichnis mit genau einer symbolischen
Verknüpfung auf /gnu/store/…-coreutils-8.22/bin/ls erstellt:
(gexp->derivation "das-ding" build-exp)
Wie man es erwarten würde, wird die Zeichenkette
"/gnu/store/…-coreutils-8.22"
anstelle der Referenzen auf das Paket
coreutils im eigentlichen Erstellungscode eingefügt und
coreutils automatisch zu einer Eingabe der Ableitung gemacht. Genauso
wird auch #$output
(was äquivalent zur Schreibweise (ungexp
output)
ist) ersetzt durch eine Zeichenkette mit dem Namen der Ausgabe der
Ableitung.
Im Kontext der Cross-Kompilierung bietet es sich an, zwischen Referenzen auf
die native Erstellung eines Pakets – also der, die auf dem
Wirtssystem ausgeführt werden kann – und Referenzen auf
Cross-Erstellungen eines Pakets zu unterscheiden. Hierfür spielt #+
dieselbe Rolle wie #$
, steht aber für eine Referenz auf eine native
Paketerstellung.
(gexp->derivation "vi"
#~(begin
(mkdir #$output)
(mkdir (string-append #$output "/bin"))
(system* (string-append #+coreutils "/bin/ln")
"-s"
(string-append #$emacs "/bin/emacs")
(string-append #$output "/bin/vi")))
#:target "aarch64-linux-gnu")
Im obigen Beispiel wird die native Erstellung der coreutils benutzt,
damit ln
tatsächlich auf dem Wirtssystem ausgeführt werden kann,
aber danach die cross-kompilierte Erstellung von emacs referenziert.
Eine weitere Funktionalität von G-Ausdrücken stellen importierte
Module dar. Manchmal will man bestimmte Guile-Module von der „wirtsseitigen
Umgebung“ im G-Ausdruck benutzen können, deswegen sollten diese Module in
die „erstellungsseitige Umgebung“ importiert werden. Die
with-imported-modules
-Form macht das möglich:
(let ((build (with-imported-modules '((guix build utils))
#~(begin
(use-modules (guix build utils))
(mkdir-p (string-append #$output "/bin"))))))
(gexp->derivation "leeres-Verzeichnis"
#~(begin
#$build
(display "Erfolg!\n")
#t)))
In diesem Beispiel wird das Modul (guix build utils)
automatisch in
die isolierte Erstellungsumgebung unseres G-Ausdrucks geholt, so dass
(use-modules (guix build utils))
wie erwartet funktioniert.
Normalerweise möchten Sie, dass der Abschluss eines Moduls importiert
wird – also das Modul und alle Module, von denen es abhängt –
statt nur das Modul selbst. Ansonsten scheitern Versuche, das Modul zu
benutzen, weil seine Modulabhängigkeiten fehlen. Die Prozedur
source-module-closure
berechnet den Abschluss eines Moduls, indem es
den Kopf seiner Quelldatei analysiert, deswegen schafft die Prozedur hier
Abhilfe:
(use-modules (guix modules)) ;„source-module-closure“ verfügbar machen (with-imported-modules (source-module-closure '((guix build utils) (gnu build image))) (gexp->derivation "etwas-mit-vm" #~(begin (use-modules (guix build utils) (gnu build image)) …)))
Auf die gleiche Art können Sie auch vorgehen, wenn Sie nicht bloß reine
Scheme-Module importieren möchten, sondern auch „Erweiterungen“ wie
Guile-Anbindungen von C-Bibliotheken oder andere „vollumfängliche“
Pakete. Sagen wir, Sie bräuchten das Paket guile-json
auf der
Erstellungsseite, dann könnten Sie es hiermit bekommen:
(use-modules (gnu packages guile)) ;für „guile-json“ (with-extensions (list guile-json) (gexp->derivation "etwas-mit-json" #~(begin (use-modules (json)) …)))
Die syntaktische Form, in der G-Ausdrücke konstruiert werden, ist im Folgenden zusammengefasst.
Liefert einen G-Ausdruck, der den Ausdruck enthält. Der Ausdruck kann eine oder mehrere der folgenden Formen enthalten:
#$Objekt
(ungexp Objekt)
Eine Referenz auf das Objekt einführen. Das Objekt kann einen
der unterstützten Typen haben, zum Beispiel ein Paket oder eine Ableitung,
so dass die ungexp
-Form durch deren Ausgabedateiname ersetzt
wird – z.B. "/gnu/store/…-coreutils-8.22
.
Wenn das Objekt eine Liste ist, wird diese durchlaufen und alle unterstützten Objekte darin auf diese Weise ersetzt.
Wenn das Objekt ein anderer G-Ausdruck ist, wird sein Inhalt eingefügt und seine Abhängigkeiten zu denen des äußeren G-Ausdrucks hinzugefügt.
Wenn das Objekt eine andere Art von Objekt ist, wird es so wie es ist eingefügt.
#$Objekt:Ausgabe
(ungexp Objekt Ausgabe)
Dies verhält sich wie die Form oben, bezieht sich aber ausdrücklich auf die angegebene Ausgabe des Objekts – dies ist nützlich, wenn das Objekt mehrere Ausgaben generiert (siehe Pakete mit mehreren Ausgaben.).
Manchmal wird in einem G-Ausdruck grundsätzlich auf die Ausgabe "out"
von etwas verwiesen, aber man möchte ihn eigentlich mit einem Verweis auf
eine andere Ausgabe einfügen. Für solche Fälle gibt es die Prozedur
gexp-input
. Siehe gexp-input.
#+Objekt
#+Objekt:Ausgabe
(ungexp-native Objekt)
(ungexp-native Objekt Ausgabe)
Das Gleiche wie ungexp
, jedoch wird im Kontext einer
Cross-Kompilierung eine Referenz auf die native Erstellung des
Objekts eingefügt.
#$output[:Ausgabe]
(ungexp output [Ausgabe])
Fügt eine Referenz auf die angegebene Ausgabe dieser Ableitung ein, oder auf die Hauptausgabe, wenn keine Ausgabe angegeben wurde.
Dies ist nur bei G-Ausdrücken sinnvoll, die an gexp->derivation
übergeben werden.
#$@Liste
(ungexp-splicing Liste)
Das Gleiche wie oben, jedoch wird nur der Inhalt der Liste in die äußere Liste eingespleißt.
#+@Liste
(ungexp-native-splicing Liste)
Das Gleiche, aber referenziert werden native Erstellungen der Objekte in der Liste.
G-Ausdrücke, die mit gexp
oder #~
erzeugt wurden, sind zur
Laufzeit Objekte vom Typ gexp?
(siehe unten).
Markiert die in Rumpf… definierten G-Ausdrücke, dass sie in ihrer Ausführungsumgebung die angegebenen Module brauchen.
Jedes Objekt unter den Modulen kann der Name eines Moduls wie
(guix build utils)
sein, oder es kann nacheinander ein Modulname, ein
Pfeil und ein dateiartiges Objekt sein:
`((guix build utils) (guix gcrypt) ((guix config) => ,(scheme-file "config.scm" #~(define-module …))))
Im Beispiel oben werden die ersten beiden Module vom Suchpfad genommen und das letzte aus dem angegebenen dateiartigen Objekt erzeugt.
Diese Form hat einen lexikalischen Sichtbarkeitsbereich: Sie wirkt sich auf die direkt in Rumpf… definierten G-Ausdrücke aus, aber nicht auf jene, die, sagen wir, in aus Rumpf… heraus aufgerufenen Prozeduren definiert wurden.
Markiert die in Rumpf… definierten G-Ausdrücke, dass sie
Erweiterungen in ihrer Erstellungs- und Ausführungsumgebung
benötigen. Erweiterungen sind typischerweise eine Liste von
Paketobjekten wie zum Beispiel die im Modul (gnu packages guile)
definierten.
Konkret werden die unter den Erweiterungen aufgeführten Pakete zum Ladepfad hinzugefügt, während die in Rumpf… aufgeführten importierten Module kompiliert werden und sie werden auch zum Ladepfad des von Rumpf… gelieferten G-Ausdrucks hinzugefügt.
Liefert #t
, wenn das Objekt ein G-Ausdruck ist.
G-Ausdrücke sind dazu gedacht, auf die Platte geschrieben zu werden, entweder als Code, der eine Ableitung erstellt, oder als einfache Dateien im Store. Die monadischen Prozeduren unten ermöglichen Ihnen das (siehe Die Store-Monade, wenn Sie mehr Informationen über Monaden suchen).
[#:hash-algo #f] [#:recursive? #f] [#:env-vars ’()] [#:modules ’()] [#:module-path %load-path
] [#:effective-version "2.2"] [#:references-graphs #f] [#:allowed-references #f] [#:disallowed-references #f] [#:leaked-env-vars #f] [#:script-name
(string-append Name "-builder")] [#:deprecation-warnings #f] [#:local-build? #f] [#:substitutable? #t] [#:properties ’()]
[#:guile-for-build #f] Liefert eine Ableitung unter dem Namen, die
jeden Ausdruck (ein G-Ausdruck) mit guile-for-build (eine
Ableitung) für das System erstellt; der Ausdruck wird dabei in
einer Datei namens script-name gespeichert. Wenn „target“ wahr
ist, wird es beim Cross-Kompilieren als Zieltripel für mit Ausdruck
bezeichnete Pakete benutzt.
modules gilt als veraltet; stattdessen sollte
with-imported-modules
benutzt werden. Die Bedeutung ist, dass die
Module im Ausführungskontext des Ausdrucks verfügbar gemacht
werden; modules ist dabei eine Liste von Namen von Guile-Modulen, die
im Modulpfad module-path gesucht werden, um sie in den Store zu
kopieren, zu kompilieren und im Ladepfad während der Ausführung des
Ausdrucks verfügbar zu machen – z.B. ((guix build utils)
(guix build gnu-build-system))
.
effective-version bestimmt, unter welcher Zeichenkette die
Erweiterungen des Ausdrucks zum Suchpfad hinzugefügt werden (siehe
with-extensions
) – z.B. "2.2"
.
graft? bestimmt, ob vom Ausdruck benannte Pakete veredelt werden sollen, falls Veredelungen zur Verfügung stehen.
Ist references-graphs wahr, muss es eine Liste von Tupeln in einer der folgenden Formen sein:
(Dateiname Objekt) (Dateiname Objekt Ausgabe) (Dateiname Gexp-Input) (Dateiname Store-Objekt)
Bei jedem Element von references-graphs wird das rechts Stehende automatisch zu einer Eingabe des Erstellungsprozesses vom Ausdruck gemacht. In der Erstellungsumgebung enthält das, was mit Dateiname bezeichnet wird, den Referenzgraphen des entsprechenden Objekts in einem einfachen Textformat.
allowed-references muss entweder #f
oder eine Liste von
Ausgabenamen und Paketen sein. Eine solche Liste benennt Store-Objekte, die
das Ergebnis referenzieren darf. Jede Referenz auf ein nicht dort
aufgeführtes Store-Objekt löst einen Erstellungsfehler aus. Genauso
funktioniert disallowed-references, was eine Liste von Objekten sein
kann, die von den Ausgaben nicht referenziert werden dürfen.
deprecation-warnings bestimmt, ob beim Kompilieren von Modulen
Warnungen angezeigt werden sollen, wenn auf als veraltet markierten Code
zugegriffen wird. deprecation-warnings kann #f
, #t
oder
'detailed
(detailliert) sein.
Die anderen Argumente verhalten sich wie bei derivation
(siehe
Ableitungen).
Die im Folgenden erklärten Prozeduren local-file
, plain-file
,
computed-file
, program-file
und scheme-file
liefern
dateiartige Objekte. Das bedeutet, dass diese Objekte, wenn sie in
einem G-Ausdruck demaskiert werden, zu einer Datei im Store
führen. Betrachten Sie zum Beispiel diesen G-Ausdruck:
#~(system* #$(file-append glibc "/sbin/nscd") "-f" #$(local-file "/tmp/my-nscd.conf"))
Der Effekt hiervon ist, dass /tmp/my-nscd.conf „interniert“ wird,
indem es in den Store kopiert wird. Sobald er umgeschrieben wurde, zum
Beispiel über gexp->derivation
, referenziert der G-Ausdruck diese
Kopie im /gnu/store. Die Datei in /tmp zu bearbeiten oder zu
löschen, hat dann keinen Effekt mehr darauf, was der G-Ausdruck
tut. plain-file
kann in ähnlicher Weise benutzt werden, es
unterscheidet sich aber darin, dass dort der Prozedur der Inhalt der Datei
als eine Zeichenkette übergeben wird.
Liefert ein Objekt, dass die lokale Datei Datei repräsentiert und sie zum Store hinzufügen lässt; dieses Objekt kann in einem G-Ausdruck benutzt werden. Wurde für die Datei ein relativer Dateiname als literaler Ausdruck angegeben, wird sie relativ zur Quelldatei gesucht, in der diese Form steht. Wurde die Datei nicht als literale Zeichenkette angegeben, wird sie zur Laufzeit relativ zum aktuellen Arbeitsverzeichnis gesucht. Die Datei wird unter dem angegebenen Namen im Store abgelegt – als Vorgabe wird dabei der Basisname der Datei genommen.
Ist recursive? wahr, werden in der Datei enthaltene Dateien rekursiv hinzugefügt; ist die Datei eine flache Datei und recursive? ist wahr, wird ihr Inhalt in den Store eingelagert und ihre Berechtigungs-Bits übernommen.
Steht recursive? auf wahr, wird (select? Datei
Stat)
für jeden Verzeichniseintrag aufgerufen, wobei Datei der
absolute Dateiname und Stat das Ergebnis von lstat
ist, außer
auf den Einträgen, wo select? keinen wahren Wert liefert.
file can be wrapped in the assume-valid-file-name
syntactic
keyword. When this is done, there will not be a warning when
local-file
is used with a non-literal path. The path is still looked
up relative to the current working directory at run time. Wrapping is done
like this:
(define alice-key-file-path "alice.pub") ;; ... (local-file (assume-valid-file-name alice-key-file-path))
file can be wrapped in the assume-source-relative-file-name
syntactic keyword. When this is done, the file name will be looked up
relative to the source file where it appears even when it is not a string
literal.
Dies ist das deklarative Gegenstück zur monadischen Prozedur
interned-file
(siehe interned-file
).
Liefert ein Objekt, das eine Textdatei mit dem angegebenen Namen repräsentiert, die den angegebenen Inhalt hat (eine Zeichenkette oder ein Bytevektor), welche zum Store hinzugefügt werden soll.
Dies ist das deklarative Gegenstück zu text-file
.
Liefert ein Objekt, das das Store-Objekt mit dem Namen repräsentiert,
eine Datei oder ein Verzeichnis, das vom G-Ausdruck berechnet
wurde. Wenn local-build? auf wahr steht (wie vorgegeben), wird auf der
lokalen Maschine erstellt. options ist eine Liste zusätzlicher
Argumente, die an gexp->derivation
übergeben werden.
Dies ist das deklarative Gegenstück zu gexp->derivation
.
(%current-system)] [#:target #f] Liefert ein ausführbares Skript namens Name, das den Ausdruck mit dem angegebenen guile ausführt, wobei vom Ausdruck importierte Module in seinem Suchpfad stehen. Die Module des Ausdrucks werden dazu im Modulpfad module-path gesucht.
Folgendes Beispiel erstellt ein Skript, das einfach nur den Befehl
ls
ausführt:
(use-modules (guix gexp) (gnu packages base)) (gexp->script "list-files" #~(execl #$(file-append coreutils "/bin/ls") "ls"))
Lässt man es durch den Store „laufen“ (siehe run-with-store
), erhalten wir eine Ableitung, die eine ausführbare
Datei /gnu/store/…-list-files generiert, ungefähr so:
#!/gnu/store/…-guile-2.0.11/bin/guile -ds !# (execl "/gnu/store/…-coreutils-8.22"/bin/ls" "ls")
Liefert ein Objekt, das eine ausführbare Store-Datei Name repräsentiert, die den G-Ausdruck ausführt. guile ist das zu verwendende Guile-Paket, mit dem das Skript ausgeführt werden kann. Importierte Module des G-Ausdrucks werden im Modulpfad module-path gesucht.
Dies ist das deklarative Gegenstück zu gexp->script
.
(default-guile)] Liefert eine Ableitung, die eine Datei Name erstellen wird, deren Inhalt der G-Ausdruck ist. Ist splice? wahr, dann wird G-Ausdruck stattdessen als eine Liste von mehreren G-Ausdrücken behandelt, die alle in die resultierende Datei gespleißt werden.
Ist set-load-path? wahr, wird in die resultierende Datei Code
hinzugefügt, der den Ladepfad %load-path
und den Ladepfad für
kompilierte Dateien %load-compiled-path
festlegt, die für die
importierten Module des G-Ausdrucks nötig sind. Die Module des
G-Ausdrucks werden im Modulpfad module-path gesucht.
Die resultierende Datei referenziert alle Abhängigkeiten des G-Ausdrucks oder eine Teilmenge davon.
Name mit dem G-Ausdruck als Inhalt repräsentiert. guile ist das zu verwendende Guile-Paket, mit dem die Datei angelegt wird.
Dies ist das deklarative Gegenstück zu gexp->file
.
Liefert eine Ableitung als monadischen Wert, welche eine Textdatei erstellt, in der der gesamte Text enthalten ist. Text kann eine Folge nicht nur von Zeichenketten, sondern auch Objekten beliebigen Typs sein, die in einem G-Ausdruck benutzt werden können, also Paketen, Ableitungen, Objekte lokaler Dateien und so weiter. Die resultierende Store-Datei referenziert alle davon.
Diese Variante sollte gegenüber text-file
bevorzugt verwendet werden,
wann immer die zu erstellende Datei Objekte im Store referenzieren
wird. Typischerweise ist das der Fall, wenn eine Konfigurationsdatei
erstellt wird, die Namen von Store-Dateien enthält, so wie hier:
(define (profile.sh)
;; Liefert den Namen eines Shell-Skripts im Store,
;; welcher die Umgebungsvariable „PATH“ initialisiert.
(text-file* "profile.sh"
"export PATH=" coreutils "/bin:"
grep "/bin:" sed "/bin\n"))
In diesem Beispiel wird die resultierende Datei /gnu/store/…-profile.sh sowohl coreutils, grep als auch sed referenzieren, so dass der Müllsammler diese nicht löscht, während die resultierende Datei noch lebendig ist.
Liefert ein Objekt, was die Store-Datei Name repräsentiert, die Text enthält. Text ist dabei eine Folge von Zeichenketten und dateiartigen Objekten wie zum Beispiel:
(mixed-text-file "profile"
"export PATH=" coreutils "/bin:" grep "/bin")
Dies ist das deklarative Gegenstück zu text-file*
.
Liefert ein <computed-file>
, das ein Verzeichnis mit allen
Dateien enthält. Jedes Objekt in Dateien muss eine
zweielementige Liste sein, deren erstes Element der im neuen Verzeichnis zu
benutzende Dateiname ist und deren zweites Element ein G-Ausdruck ist, der
die Zieldatei benennt. Hier ist ein Beispiel:
(file-union "etc"
`(("hosts" ,(plain-file "hosts"
"127.0.0.1 localhost"))
("bashrc" ,(plain-file "bashrc"
"alias ls='ls --color=auto'"))))
Dies liefert ein Verzeichnis etc
, das zwei Dateien enthält.
Liefert ein Verzeichnis, was die Vereinigung der Dinge darstellt, wobei Dinge eine Liste dateiartiger Objekte sein muss, die Verzeichnisse bezeichnen. Zum Beispiel:
(directory-union "guile+emacs" (list guile emacs))
Das liefert ein Verzeichnis, welches die Vereinigung der Pakete guile
und emacs
ist.
Liefert ein dateiartiges Objekt, das zur Aneinanderreihung von Objekt und Suffix umgeschrieben wird, wobei das Objekt ein herunterbrechbares Objekt und jedes Suffix eine Zeichenkette sein muss.
Betrachten Sie zum Beispiel diesen G-Ausdruck:
(gexp->script "uname-ausfuehren"
#~(system* #$(file-append coreutils
"/bin/uname")))
Denselben Effekt könnte man erreichen mit:
(gexp->script "uname-ausfuehren"
#~(system* (string-append #$coreutils
"/bin/uname")))
Es gibt jedoch einen Unterschied, nämlich enthält das resultierende Skript
bei file-append
tatsächlich den absoluten Dateinamen als
Zeichenkette, während im anderen Fall das resultierende Skript einen
Ausdruck (string-append …)
enthält, der den Dateinamen erst zur
Laufzeit zusammensetzt.
System an das System binden, für das momentan erstellt wird –
z.B. "x86_64-linux"
–, während der Rumpf ausgeführt
wird.
In der zweiten Form wird zusätzlich das Ziel an das aktuelle Ziel
(„Target“) bei der Cross-Kompilierung gebunden. Dabei handelt es sich um ein
GNU-Tripel wie z.B. "arm-linux-gnueabihf"
– oder um #f
,
wenn nicht cross-kompiliert wird.
let-system
zu benutzen, bietet sich dann an, wenn einmal das in den
G-Ausdruck gespleißte Objekt vom Zielsystem abhängen sollte, wie in diesem
Beispiel:
#~(system* #+(let-system system (cond ((string-prefix? "armhf-" system) (file-append qemu "/bin/qemu-system-arm")) ((string-prefix? "x86_64-" system) (file-append qemu "/bin/qemu-system-x86_64")) (else (error "weiß nicht!")))) "-net" "user" #$image)
Mit diesem Makro verhält es sich ähnlich wie mit der
parameterize
-Form für dynamisch gebundene Parameter (siehe
Parameters in Referenzhandbuch zu GNU Guile). Der
Hauptunterschied ist, dass es sich erst auswirkt, wenn das vom
Ausdruck zurückgelieferte dateiartige Objekt auf eine Ableitung oder
ein Store-Objekt heruntergebrochen wird.
Eine typische Anwendung von with-parameters
ist, den für ein
bestimmtes Objekt geltenden Systemtyp zwingend festzulegen:
(with-parameters ((%current-system "i686-linux"))
coreutils)
Obiges Beispiel liefert ein Objekt, das der Erstellung von Coreutils für die
i686-Architektur entspricht, egal was der aktuelle Wert von
%current-system
ist.
Liefert ein gexp-input-Verbundsobjekt, das für die Ausgabe des
dateiartigen Objekts Objekt steht. Dabei legt man mit #:native?
fest, ob eine native Erstellung referenziert wird (wie bei
ungexp-native
) oder nicht.
Diese Prozedur verwendet man, um eine Referenz auf eine bestimmte Ausgabe eines Objekts an eine Prozedur zu übergeben, in der keine Ausgabe ausgewählt wird. Zum Beispiel, wenn Sie diese Prozedur vorliegen haben, die ein dateiartiges Objekt entgegennimmt:
(define (make-symlink Ziel)
(computed-file "eine-symbolische-verknüpfung"
#~(symlink #$Ziel #$output)))
Mit make-symlink
wird hier für sich alleine immer auf die
Standardausgabe von Ziel verwiesen – also auf die Ausgabe
"out"
(siehe Pakete mit mehreren Ausgaben.). Um die Prozedur
auf z.B. die Ausgabe "lib"
des Pakets hwloc
verweisen zu
lassen, ruft man sie so auf:
(make-symlink (gexp-input hwloc "lib"))
Auch eine Komposition mit Funktionen für dateiartige Objekte ist möglich:
(make-symlink
(file-append (gexp-input hwloc "lib") "/lib/libhwloc.so"))
Natürlich gibt es zusätzlich zu in „wirtsseitigem“ Code eingebetteten
G-Ausdrücken auch Module mit „erstellungsseitig“ nutzbaren Werkzeugen. Um
klarzustellen, dass sie dafür gedacht sind, in der Erstellungsschicht
benutzt zu werden, bleiben diese Module im Namensraum (guix build …)
.
Intern werden hochsprachliche, abstrakte Objekte mit ihrem Compiler entweder
zu Ableitungen oder zu Store-Objekten heruntergebrochen. Wird zum
Beispiel ein Paket heruntergebrochen, bekommt man eine Ableitung, während
ein plain-file
zu einem Store-Objekt heruntergebrochen wird. Das wird
mit der monadischen Prozedur lower-object
bewerkstelligt.
Objekt für System als Wert in der Store-Monade
%store-monad
entspricht, cross-kompiliert für das Zieltripel
target, wenn target wahr ist. Das Objekt muss ein Objekt
sein, für das es einen mit ihm assoziierten G-Ausdruck-Compiler gibt, wie
zum Beispiel ein <package>
.
Es kann gelegentlich nützlich sein, einen G-Ausdruck in einen S-Ausdruck
umzuwandeln, weil zum Beispiel manche Prüfer (siehe guix lint
aufrufen) einen Blick auf die Erstellungsphasen eines Pakets werfen, um
mögliche Fehler zu finden. Diese Umwandlung können Sie mit dieser Prozedur
bewerkstelligen. Allerdings kann dabei manche Information verloren
gehen. Genauer gesagt werden herunterbrechbare Objekte stillschweigend durch
ein beliebiges Objekt ersetzt. Zurzeit ist dieses beliebige Objekt die Liste
(*approximate*)
, aber verlassen Sie sich nicht darauf, dass es so
bleibt.
Der Begriff Schicht, englisch Stratum, wurde in diesem Kontext von Manuel Serrano et al. in ihrer Arbeit an Hop geprägt. Oleg Kiselyov, der aufschlussreiche Essays und Code zu diesem Thema geschrieben hat, nennt diese Art der Code-Generierung Staging, deutsch etwa Inszenierung bzw. Aufführung.
Nächste: guix repl
aufrufen, Vorige: Die Store-Monade, Nach oben: Programmierschnittstelle [Inhalt][Index]