Nächste: Werkzeuge zur Erstellung, Vorige: Erstellungssysteme, Nach oben: Programmierschnittstelle [Inhalt][Index]
Fast alle Erstellungssysteme für Pakete implementieren ein Konzept von
Erstellungsphasen: einer Abfolge von Aktionen, die vom
Erstellungssystem ausgeführt werden, wenn Sie das Paket erstellen. Dabei
fallen in den Store installierte Nebenerzeugnisse an. Eine Ausnahme ist der
Erwähnung wert: das magere trivial-build-system
(siehe Erstellungssysteme).
Wie im letzten Abschnitt erläutert, stellen diese Erstellungssysteme eine
standardisierte Liste von Phasen zur Verfügung. Für gnu-build-system
sind dies die hauptsächlichen Erstellungsphasen:
set-paths
Suchpfade in Umgebungsvariablen definieren. Dies geschieht für alle
Eingabepakete. PATH
wird so auch festgelegt. Siehe Suchpfade.
unpack
Den Quell-Tarball entpacken und das Arbeitsverzeichnis wechseln in den entpackten Quellbaum. Wenn die Quelle bereits ein Verzeichnis ist, wird es in den Quellbaum kopiert und dorthin gewechselt.
patch-source-shebangs
„Shebangs“ in Quelldateien beheben, damit Sie sich auf die richtigen
Store-Dateipfade beziehen. Zum Beispiel könnte #!/bin/sh
zu
#!/gnu/store/…-bash-4.3/bin/sh
geändert werden.
configure
Das Skript configure mit einigen vorgegebenen Befehlszeilenoptionen
ausführen, wie z.B. mit --prefix=/gnu/store/…, sowie mit den im
#:configure-flags
-Argument angegebenen Optionen.
build
make
ausführen mit den Optionen aus der Liste in
#:make-flags
. Wenn das Argument #:parallel-build?
auf wahr
gesetzt ist (was der Vorgabewert ist), wird make -j
zum Erstellen
ausgeführt.
check
make check
(oder statt check
ein anderes bei
#:test-target
angegebenes Ziel) ausführen, außer falls #:tests?
#f
gesetzt ist. Wenn das Argument #:parallel-tests?
auf wahr gesetzt
ist (der Vorgabewert), führe make check -j
aus.
install
make install
mit den in #:make-flags
aufgelisteten Optionen
ausführen.
patch-shebangs
Shebangs in den installierten ausführbaren Dateien beheben.
strip
Symbole zur Fehlerbehebung aus ELF-Dateien entfernen (außer
#:strip-binaries?
ist auf falsch gesetzt) und in die
debug
-Ausgabe kopieren, falls diese verfügbar ist (siehe
Dateien zur Fehlersuche installieren).
validate-runpath
Den RUNPATH
von ELF-Binärdateien validieren, sofern
#:validate-runpath?
falsch ist (siehe Erstellungssysteme).
Die Validierung besteht darin, sicherzustellen, dass jede gemeinsame
Bibliothek, die von einer ELF-Binärdatei gebraucht wird (sie sind in
DT_NEEDED
-Einträgen im PT_DYNAMIC
-Segment der ELF-Datei
aufgeführt), im DT_RUNPATH
-Eintrag der Datei gefunden wird. Mit
anderen Worten wird gewährleistet, dass es beim Ausführen oder Benutzen
einer solchen Binärdatei nicht zur Laufzeit zu einem Fehler kommt, eine
Datei würde nicht gefunden. Siehe -rpath in The
GNU Linker für mehr Informationen zum RUNPATH
.
Andere Erstellungssysteme haben ähnliche, aber etwas unterschiedliche
Phasen. Zum Beispiel hat das cmake-build-system
gleichnamige Phasen,
aber seine configure
-Phase führt cmake
statt
./configure
aus. Andere Erstellungssysteme wie z.B.
python-build-system
haben eine völlig andere Liste von
Standardphasen. Dieser gesamte Code läuft erstellungsseitig: Er wird
dann ausgewertet, wenn Sie das Paket wirklich erstellen, in einem eigenen
Erstellungprozess nur dafür, den der Erstellungs-Daemon erzeugt (siehe
Aufruf von guix-daemon
).
Erstellungsphasen werden durch assoziative Listen (kurz „Alists“) repräsentiert (siehe Association Lists in Referenzhandbuch zu GNU Guile) wo jeder Schlüssel ein Symbol für den Namen der Phase ist und der assoziierte Wert eine Prozedur ist, die eine beliebige Anzahl von Argumenten nimmt. Nach Konvention empfangen diese Prozeduren dadurch Informationen über die Erstellung in Form von Schlüsselwort-Parametern, die darin benutzt oder ignoriert werden können.
Zum Beispiel werden die %standard-phases
, das ist die Variable mit
der Alist der Erstellungsphasen, in (guix build gnu-build-system)
so
definiert21:
;; Die Erstellungsphasen von 'gnu-build-system'. (define* (unpack #:key source #:allow-other-keys) ;; Quelltarball extrahieren. (invoke "tar" "xvf" source)) (define* (configure #:key outputs #:allow-other-keys) ;; 'configure'-Skript ausführen. In Ausgabe "out" installieren. (let ((out (assoc-ref outputs "out"))) (invoke "./configure" (string-append "--prefix=" out)))) (define* (build #:allow-other-keys) ;; Kompilieren. (invoke "make")) (define* (check #:key (test-target "check") (tests? #true) #:allow-other-keys) ;; Testkatalog ausführen. (if tests? (invoke "make" test-target) (display "test suite not run\n"))) (define* (install #:allow-other-keys) ;; Dateien ins bei 'configure' festgelegte Präfix installieren. (invoke "make" "install")) (define %standard-phases ;; Die Liste der Standardphasen (der Kürze halber lassen wir einige ;; aus). Jedes Element ist ein Paar aus Symbol und Prozedur. (list (cons 'unpack unpack) (cons 'configure configure) (cons 'build build) (cons 'check check) (cons 'install install)))
Hier sieht man wie %standard-phases
als eine Liste von Paaren aus
Symbol und Prozedur (siehe Pairs in Referenzhandbuch zu GNU
Guile) definiert ist. Das erste Paar assoziiert die unpack
-Prozedur
mit dem unpack
-Symbol – es gibt einen Namen an. Das zweite Paar
definiert die configure
-Phase auf ähnliche Weise, ebenso die
anderen. Wenn ein Paket erstellt wird, das gnu-build-system
benutzt,
werden diese Phasen der Reihe nach ausgeführt. Sie können beim Erstellen von
Paketen im Erstellungsprotokoll den Namen jeder gestarteten und
abgeschlossenen Phase sehen.
Schauen wir uns jetzt die Prozeduren selbst an. Jede davon wird mit
define*
definiert, dadurch können bei #:key
die
Schlüsselwortparameter aufgelistet werden, die die Prozedur annimmt, wenn
gewünscht auch zusammen mit einem Vorgabewert, und durch
#:allow-other-keys
wird veranlasst, dass andere
Schlüsselwortparameter ignoriert werden (siehe Optional Arguments in Referenzhandbuch zu GNU Guile).
Die unpack
-Prozedur berücksichtigt den source
-Parameter; das
Erstellungssystem benutzt ihn, um den Dateinamen des Quell-Tarballs (oder
des Checkouts aus einer Versionskontrolle) zu finden. Die anderen Parameter
ignoriert sie. Die configure
-Phase interessiert sich nur für den
outputs
-Parameter, eine Alist, die die Namen von Paketausgaben auf
ihre Dateinamen im Store abbildet (siehe Pakete mit mehreren Ausgaben.). Sie extrahiert den Dateinamen für out
, die
Standardausgabe, und gibt ihn an ./configure
als das
Installationspräfix weiter, wodurch make install
zum Schluss alle
Dateien in dieses Verzeichnis kopieren wird (siehe configuration and makefile conventions in GNU Coding
Standards). build
und install
ignorieren all ihre
Argumente. check
berücksichtigt das Argument test-target
,
worin der Name des Makefile-Ziels angegeben wird, um die Tests
auszuführen. Es wird stattdessen eine Nachricht angezeigt und die Tests
übersprungen, wenn tests?
falsch ist.
Die Liste der Phasen, die für ein bestimmtes Paket benutzt werden, kann über
den #:phases
-Parameter an das Erstellungssystem geändert werden. Das
Ändern des Satzes von Erstellungsphasen funktioniert so, dass eine neue
Alist von Phasen aus der oben beschriebenen %standard-phases
-Alist
heraus erzeugt wird. Dazu können die Standardprozeduren zur Bearbeitung von
assoziativen Listen wie alist-delete
benutzt werden (siehe
SRFI-1 Association Lists in Referenzhandbuch zu GNU Guile),
aber es ist bequemer, dafür die Prozedur modify-phases
zu benutzen
(siehe modify-phases
).
Hier ist ein Beispiel für eine Paketdefinition, die die
configure
-Phase aus %standard-phases
entfernt und eine neue
Phase vor der build
-Phase namens set-prefix-in-makefile
einfügt:
(define-public beispiel
(package
(name "beispiel")
;; wir lassen die anderen Felder aus
(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)
;; Makefile anpassen, damit die 'PREFIX'-
;; Variable auf "out" verweist.
(let ((out (assoc-ref outputs "out")))
(substitute* "Makefile"
(("PREFIX =.*")
(string-append "PREFIX = "
out "\n")))))))))))
Die neu eingefügte Phase wurde als anonyme Prozedur geschrieben. Solche
namenlosen Prozeduren schreibt man mit lambda*
. Oben berücksichtigt
sie den outputs
-Parameter, den wir zuvor gesehen haben. Siehe
Werkzeuge zur Erstellung für mehr Informationen über die in dieser Phase
benutzten Hilfsmittel und für mehr Beispiele zu modify-phases
.
Sie sollten im Kopf behalten, dass Erstellungsphasen aus Code bestehen, der
erst dann ausgewertet wird, wenn das Paket erstellt wird. Das ist der Grund,
warum der gesamte modify-phases
-Ausdruck oben quotiert wird. Quotiert
heißt, er steht nach einem '
oder Apostrophenzeichen: Er wird nicht
sofort als Code ausgewertet, sondern nur zur späteren Ausführung vorgemerkt
(wir sagen staged, siehe G-Ausdrücke für eine Erläuterung von
Code-Staging und den beteiligten Code-Schichten (oder „Strata“).
Wir stellen hier nur eine vereinfachte Sicht auf diese
Erstellungsphasen vor. Wenn Sie alle Details wollen, schauen Sie sich
(guix build gnu-build-system)
an!
Nächste: Werkzeuge zur Erstellung, Vorige: Erstellungssysteme, Nach oben: Programmierschnittstelle [Inhalt][Index]