| RPM-MACROS(7) | Miscellaneous Information Manual | RPM-MACROS(7) |
BEZEICHNUNG¶
rpm-macros - RPM-Makroprozessor
ÜBERSICHT¶
Definieren¶
%NAME TEXTKÖRPER
%NAME([OPTIONEN]) TEXTKÖRPER
Expandieren¶
%NAME
%NAME [OPTIONEN] [ARGUMENTE]
%{NAME}
%{NAME [OPTIONEN] ARGUMENTE}
%{NAME:ARGUMENT}
%{?NAME}
%{?NAME:WERT-FALLS-DEFINIERT}
%{!?NAME:WERT-FALLS-NICHT-DEFINIERT}
%(SHELL-BEFEHL)
%[AUSDRUCK]
%[AUSDRUCK ? WERT-FALLS-WAHR : WERT-FALLS-FALSCH]
%{lua:LUA-CODE}
BESCHREIBUNG¶
RPM verfügt über einen leistungsstarken integrierten Makroprozessor. Makros werden hauptsächlich für die Konfiguration und andere Dienstprogrammfunktionen von RPM selbst sowie als Paketierungshilfe in Spec-Dateien verwendet.
Neben der einfachen Textersetzung unterstützt der Makroprozessor die folgenden Funktionen:
- funktionsähnliche PARAMETRISCHE MAKROS mit Optionen und Argumentverarbeitung sowie lokal begrenzten automatischen und benutzerdefinierten Makros
- Shell-Expansion
- Ausdrucksexpansion
- Lua-Expansion für die eingebettete Lua-Verarbeitung
- verschiedene EINGEBAUTE MAKROS für die Verarbeitung von Zeichenketten und Interaktion mit dem Betriebssystem
Die Syntax zum Definieren einfacher Makros lautet:
Jeglicher Leerraum um den TEXTKÖRPER wird entfernt. Der NAME kann aus alphanumerischen Zeichen und dem Unterstrich (_) bestehen und muss mindestens zwei Zeichen lang sein. Der Textkörper wird bei jedem Makroaufruf (erneut) expandiert. Bei Makronamen und -optionen wird die Groß- und Kleinschreibung beachtet.
Siehe PARAMETRISCHE MAKROS für die fortgeschrittene Makrovariante mit Options- und Argumentverarbeitung.
Makros können über rpm-macrofile(5)-Dateien definiert und vollständig mit den Makroprimitiven %define, %global und %undefine, der RPM-Befehlszeile (beschrieben in rpm-common(8)) und der API (C, Python, Lua) verwaltet werden.
Mit Ausnahme derjenigen, die in parametrischen Makros definiert sind, haben Makros immer einen globalen Gültigkeitsbereich.
RPM-Makros werden gestapelt, das heißt, wenn ein bereits vorhandenes Makro neu definiert wird, wird die vorherige Definition lediglich überdeckt, anstatt sie zu ersetzen. Beim Aufheben der Definition eines Makros wird nur die oberste Definition entfernt, wodurch die vorherige Makrodefinition wieder aktiviert wird.
Beachten Sie, dass diese Handbuchseite nur die Makroprozessor-Engine selbst beschreibt. Auf einem normalen RPM-basierten System gibt es eine Vielzahl weiterer Makros, die über rpm-macrofile(5)-Dateien definiert sind und hier nicht behandelt werden.
EXPANSION¶
Um ein Makro zu expandieren, stellen Sie ein % voran. Es werden mehrere Formen unterstützt:
%NAME
%{NAME}
%NAME [OPTIONEN] [ARGUMENTE]
-- kann dazu verwendet werden, Optionen von Argumenten zu trennen.
%{NAME [OPTIONEN] [ARGUMENTE]}
%{NAME:ARGUMENT}
Hinweis: Die Syntax für den Aufruf parametrischer und eingebauter Makros ist jetzt generell austauschbar, aber vor Version 4.18 war die Syntax %{NAME:ARGUMENT} auf eingebaute Makros beschränkt.
Die Makroexpansion kann durch Platzieren eines zweiten % vor dem Makro vermieden werden. Beispielsweise würde %%{name} zu %{name} expandiert.
Der Versuch, ein undefiniertes Makro zu expandieren, führt zum wörtlichen Aufruf, z.B. wird %_undefined zu %_undefined. Wenn dies nicht erwünscht ist, verwenden Sie Bedingungen.
Makro-Expansionen können bis zu 64 Ebenen rekursiv sein.
Shell-Expansion¶
Die Shell-Expansion kann mit %(Shell-Befehl) durchgeführt werden. Der Shell_Befehl wird expandiert, bevor er mit /bin/sh ausgeführt wird, dessen Ausgabe die Expansion des Makros darstellt. Der abschließende Zeilenumbruch wird gelöscht.
Beispiel:
%(echo aa-bb-cc | tr '-' '.')
Bedingte Expansion¶
Der Makroprozessor unterstützt das Testen, ob ein Makro definiert ist oder nicht.
%{?NAME:WERT}
%{!?NAME:WERT}
%{?NAME}
Für komplexere Tests verwenden Sie die Expansion von Ausdrücken oder die Lua-Expansion. Beachten Sie, dass %if, %ifarch und ähnliche keine Makros, sondern Spec-Datei-Direktiven und nur in diesem Kontext verwendbar sind.
Beachten Sie, dass in RPM >= 4.17 Bedingungen für integrierte Makros lediglich die Existenz des integrierten Makros prüfen, genau wie bei allen anderen Makros. In älteren Versionen ist das Verhalten von Bedingungen für integrierte Makros undefiniert.
Expansion von Ausdrücken¶
Ausdrücke können in der Form %[AUSDRUCK] expandiert werden. Ein Ausdruck besteht aus Termen, die mittels Operatoren kombiniert werden können.
RPM unterstützt drei Arten von Termen:
- Zahlen, bestehend aus Ziffern
- in hochgestellte doppelte Anführungszeichen eingeschlossene Zeichenketten (z.B. "Zeichenkette")
- in hochgestellte doppelte Anführungszeichen eingeschlossene Versionen, denen ein v vorangestellt ist (z.B. v"3:1.2-1")
RPM expandiert Makros, wenn Terme ausgewertet werden.
Sie können die Standard-Operatoren verwenden, um Terme zu verknüpfen:
- die logischen Operatoren &&, ||, !
- die relationalen Operatoren !=, ==, <, >, <=, >=
- die arithmetischen Operatoren +, -, /, *,
- den ternären Operator ? :
- Klammern
Beispielsweise wird %[ 3 + 4 * (1 + %two) ] zu 15 expandiert, wenn %two zu 2 expandiert wird. Versionsterme werden mit dem RPM-Versionsvergleichsalgorithmus ([Epoche:]Version[-Veröffentlichung]) verglichen, nicht mit einem regulären Zeichenkettenvergleich.
Beachten Sie, dass sich die Expansion der Form %[AUSDRUCK] vom Makro %{expr:AUSDRUCK} unterscheidet. Bei Letzterem werden zuerst die Makros im Ausdruck expandiert und dann der Ausdruck ausgewertet (ohne die Terme erneut zu expandieren). Somit wird
rpm --define 'foo 1 + 2' --eval '%{expr:%foo}'
3 ausgeben. Wenn Sie stattdessen %[%bla] verwenden, wird eine Fehlermeldung ausgegeben, dass »1 + 2« keine Zahl ist.
Die Makroexpansion bei der Auswertung der Terme durchzuführen hat zwei Vorteile. Erstens ermöglicht sie RPM eine korrekte verkürzte Verarbeitung bei der Auswertung von logischen Operatoren. Zweitens beeinflusst das Expansionsergebnis nicht die Auswertung von Ausdrücken. Beispielsweise funktioniert %["%file"] selbst dann, wenn das Makro %file zu einer Zeichenkette mit doppelten englischen Anführungszeichen expandiert wird.
Hinzugefügt: 4.16.0
Lua-Expansion¶
Die leistungsstärkste Methode zur Makroexpansion ist die Verwendung des in RPM eingebetteten Lua-Interpreters:
%{lua:LUA-CODE}
Weitere Details finden Sie in rpm-lua(7).
PARAMETRISCHE MAKROS¶
Parametrische Makros sind ein leistungsstarker Mechanismus, der die Erstellung funktionsähnlicher Dienstprogramm-Makros mit Optionsverarbeitung und der Annahme einer variablen Anzahl von Argumenten ermöglicht, ähnlich wie bei gängigen Shell-Werkzeugen.
Ein parametrisches Makro wird nach folgender Syntax definiert:
Falls vorhanden, werden die OPTIONEN (das heißt, die Zeichenkette in Klammern) genau so an getopt(3) zur argc/argv-Verarbeitung zu Beginn eines Makroaufrufs übergeben. Es werden nur kurze Optionen unterstützt.
- als einziges OPTIONEN-Feld deaktiviert die Optionsverarbeitung von RPM. Dadurch können Makros vollständig entscheiden, wie sie mit ihren Eingaben umgehen. Wenn zum Beispiel die Argumente des Makros ausschließlich oder hauptsächlich aus Elementen bestehen, die mit - beginnen, ist die Standardverarbeitung nur hinderlich.
Automatische Makros¶
Während ein parametrisiertes Makro expandiert wird, stehen die folgenden Shell-ähnlichen automatischen Makros zur Verfügung:
| Makro | Beschreibung |
| %0 | der Name des aufgerufenen Makros |
| %* | alle Argumente (im Gegensatz zur Shell, ohne verarbeitete Schalter) |
| %** | alle Argumente (einschließlich aller verarbeiteten Schalter) |
| %# | die Anzahl der Argumente |
| %{-f} | falls beim Aufruf vorhanden, das letzte Vorkommen des Schalters f (Schalter und Argument) |
| %{-f*} | falls beim Aufruf vorhanden, das Argument für das letzte Vorkommen des Schalters f |
| %1, %2, … | die Argumente selbst (nach der Verarbeitung mit getopt(3)) |
Wenn die integrierte Optionsverarbeitung mit - als OPTIONEN-Feld deaktiviert wurde, sind nur die folgenden automatischen Makros verfügbar:
| Makro | Beschreibung |
| %0 | der Name des aufgerufenen Makros |
| %*, %** | alle Argumente |
| %# | die Anzahl der Argumente |
| %1, %2, … | die Argumente selbst |
Automatische Makros werden beim Ein- und Ausstieg aus parametrischen Makros automatisch definiert und undefiniert.
Zugriff auf Optionen¶
Im Textkörper eines parametrischen Makros gibt es mehrere Konstrukte, die das Testen auf das Vorhandensein optionaler Parameter ermöglichen. Das einfachste Konstrukt ist %{-f}, das (wörtlich) zu -f expandiert wird, wenn -f beim Aufruf des Makros übergeben wurde. Es gibt auch Möglichkeiten, Text einzufügen, wenn ein Schalter vorhanden ist, indem %{-f:X} verwendet wird. Dieses Makro expandiert zu (der Expansion von) X, wenn der Schalter vorhanden war. Die negierte Form %{!-f:Y}, die zu (der Expansion von) Y expandiert, wenn -f nicht vorhanden war, wird ebenfalls unterstützt.
Bereich und Sichtbarkeit¶
Im Allgemeinen haben Makros einen globalen Gültigkeitsbereich, unabhängig davon, wo und wie sie definiert wurden. Makros, die innerhalb parametrischer Makros definiert sind, haben jedoch einen nicht-globalen Gültigkeitsbereich, und zwar wie folgt:
- Automatische Makros haben einen lokalen Gültigkeitsbereich, das heißt, sie sind nur auf der Aufrufebene des Makros selbst sichtbar.
- Benutzerdefinierte lokale Makros haben einen verschachtelten Gültigkeitsbereich, das heißt, sie sind auf der Aufrufebene des Makros selbst und tiefer sichtbar.
Das heißt, ein parametrisches Makro kann die Optionen oder Argumente eines anderen nicht sehen, aber auf ein benutzerdefiniertes lokales Makro in einem aufrufenden Makro kann in den aufgerufenen Makros zugegriffen werden.
Um ein globales Makro innerhalb eines parametrischen Makros zu definieren, müssen Sie %global anstelle von %define verwenden. Beachten Sie außerdem, dass %global den Makrokörper zum Zeitpunkt der Definition einmal expandiert, da ein solches Makro möglicherweise auf andere Makros verweist, die nur im aktuellen Bereich sichtbar sind.
Aufrufkonvention¶
Beim Expandieren eines parametrischen Makros wird die folgende Aufrufkonvention verwendet:
- 1.
- alle Argumente des Makros werden auf der Aufrufebene des Aufrufenden expandiert
- 2.
- alle Optionen des Makros werden verarbeitet
- 3.
- automatische Makros werden für die Optionen und die Argumente eingerichtet
- 4.
- der Makrokörper wird rekursiv expandiert
- 5.
- alle auf dieser Aufrufebene definierten Makros werden verworfen
EINGEBAUTE MAKROS¶
RPM verfügt über die in der nachfolgenden Liste aufgeführten eingebauten Makros für verschiedene Aktionen. Eingebaute Makros können nicht undefiniert oder außer Kraft gesetzt werden.
Hinweis: Der Stil %{Name:Argument} wird hier verwendet, da er am abwärtskompatibelsten ist und keine Anführungszeichen für Leerraum erfordert. Er kann aber grundsätzlich auch durch die anderen Expandierungsformen ersetzt werden. Integrierte Funktionen mit mehreren Argumenten müssen andere Stile verwenden, wie nachfolgend angegeben.
Manipulation von Makros¶
Die Makroprimitive werden zur Makromanipulation in Spec-Dateien und anderen Makros verwendet. Beachten Sie, dass alle diese auf dem Makronamen ohne das vorangehende %-Zeichen arbeiten.
%define NAME[([OPTIONEN])] TEXTKÖRPER
Beispiel:
%define meinpfad /usr/bin/mein
%global NAME[([OPTIONEN])] TEXTKÖRPER
Der zweite Unterschied besteht darin, dass der TEXTKÖRPER bei der Definition einmalig expandiert wird und die Expansion zum eigentlichen Makrokörper wird. Daher kann es bei Verwendung von %global je nach Inhalt und den anderen im TEXTKÖRPER verwendeten Makros zu beliebiger Codeausführung und Nebeneffekten kommen. Dass die Expansion zum eigentlichen Makrokörper wird, kann praktisch sein, um, falls sich der Wert nicht ändert, redundante, möglicherweise aufwändige Makroexpansionen zu vermeiden. Beachten Sie jedoch die Nebeneffekte.
Beachten Sie, dass %global zwar technisch gesehen ein OPTIONEN-Feld akzeptiert, es jedoch aufgrund des TEXTKÖRPER-Expansionsverhaltens nicht für die Definition parametrischer Makros geeignet ist.
Beispiel:
%global snapver 0-0.48.20240616git
%undefine NAME
Beispiel:
%undefine mein_Pfad
%{load:DATEI}
Beispiel:
%{load:/irgendein/verzeichnis/makros.foo}
Makro-Expansion¶
%{expand:TEXTKÖRPER}
Beispiel:
%{expand:%{foo_präfix}%{foo_suffix}}
%{expr:AUSDRUCK}
Beispiel:
%{expr:5*1024}
%{lua:LUA-CODE}
Beispiel:
%{lua:for i=65,90 do print(string.char(i)) end}
%{macrobody:NAME}
Beispiel:
%{macrobody:_libdir}
Zeichenkettenaktionen¶
%dnl
Beispiel:
%dnl Dies ist ein Kommentar zum Verhalten von %{mymacro}
%{gsub ZEICHENKETTE, MUSTER, ERSETZUNG [,N]}
Hinzugefügt: 4.19.0
Beispiel:
%{gsub aabbaacc aa dd 1}
%{len:ZEICHENKETTE}
Beispiel:
%{len:9bf7da058a7c582878310e75be3d56a5a8b67f95}
%{lower:ZEICHENKETTE}
Beispiel:
%{lower:CamelCase}'
%{quote:ZEICHENKETTE}
Beispiel:
%myzip -x %{quote:empty spaces.zip}
%{rep ZEICHENKETTE, N [,TRENNER]}
Hinzugefügt: 4.19.0
Beispiel:
%{rep a 5}
%{reverse:ZEICHENKETTE}
Beispiel:
%{reverse:tac}
%{shescape:ZEICHENKETTE}
Beispiel:
%{shescape:foo's}
%{shrink:ZEICHENKETTE}
Beispiel:
%{shrink:aa bb ccc }
%{span:ZEICHENKETTE}
Beispiel:
%{span:
%one thing
%another thing
}
%{sub ZEICHENKETTE, I, [,J]}
Hinzugefügt: 4.19.0
Beispiel:
*%{sub meinedatei.zip 3 6}*
%{upper:ZEICHENKETTE}
Beispiel:
%{upper:CamelCase}'
Datei- und Pfadaktionen¶
%{basename:PFAD}
%{dirname:PFAD}
%{exists:PFAD}
Beispiel:
%{exists:%{builddir}/meinschalter.txt}
%{suffix:PFAD}
Beispiel:
%{suffix:meinedatei.zip}
%{url2path:URL}
Beispiel:
%{uncompress:PFAD}
Beispiel:
%{uncompress /meine/quelldatei.tar.gz}
%{xdg:ART}
- cache: benutzerspezifische nicht wesentliche (zwischengespeicherte) Daten
- config: benutzerspezifische Konfigurationsdateien
- data: benutzerspezifische Datendateien
- state: benutzerspezifische Statusdateien
Hinzugefügt: 6.0.0
Beispiel:
%{xdg config}
Infos zur Umgebung¶
%getncpus
%{getncpus:ART}
- total: Gesamtanzahl der verfügbaren CPUs (gleichbedeutend mit %getncpus)
- proc: Anzahl der für Prozesse verfügbaren CPUs
- thread: Anzahl der für Threads verfügbaren CPUs
proc und thread berücksichtigen den verfügbaren Speicher, einschließlich Adressraumbeschränkungen für Threads.
Hinzugefügt: 4.19.0.
Beispiel:
%{getncpus proc}
%getconfdir
%{getenv:NAME}
%rpmversion
Ausgabe¶
%{echo:ZEICHENKETTE}
Beispiel:
%{echo:Building with foo}
%{warn:ZEICHENKETTE}
Beispiel:
%{warning:Foo is deprecated}
%{error:ZEICHENKETTE}
Beispiel:
%{error:Invalid argument}
%verbose
%{verbose:ZEICHENKETTE}
Beispiel:
%{verbose:-x}
Spec-spezifische Makros¶
%{S:NUMMER}
%{P:NUMMER}
Diagnostik¶
%trace
%dump
%__file_name
%__file_lineno
BEISPIELE¶
Beispiel 1: Definieren eines einfachen Makros¶
Das Makro mylib in einer Spec-Datei auf einen Pfad relativ zum %{_libdir}-Makro setzen:
%define mylib %{_libdir}/mein
Beispiel 2: Ein parametrisches Makro definieren¶
Das parametrische Makro myhelper definieren, das das durch %myprog angegebene Programm mit seinem ersten Argument ausführt und ihm immer die Option --some-opt übergibt, sowie zusätzlich die Option --xtra, wenn es selbst die Option -x erhalten hat:
%define myhelper(x) %{myprog} --some-opt %{?-x:--xtra} %{1}
Beispiel 3: Ein Makro mittels Shell-Expansion definieren¶
Definieren des Makros %today, das mithilfe des Shell-Dienstprogramms date(1) zum aktuellen Datum im Format JJMMTT expandiert. Beachten Sie das zweite %, das zum Maskieren der Argumente für date(1) benötigt wird:
%define today %(date +%%y%%m%%d)
Beispiel 4: Ein bedingtes Makro definieren¶
Das Makro mypath definieren, sofern es nicht bereits zuvor definiert wurde:
%{!?mypath: %define mypath /ir/gend/wo}
Beispiel 5: Bedingte Expansion¶
Expandiert zu 1, falls use_foo definiert ist, anderenfalls zu 0:
%{?use_foo:1}%{!?use_foo:0}
Beispiel 6 – Ausdrücke¶
5 * 1024 berechnen:
%[5 * 1024]
Zu wörtlichem true oder false expandieren, abhängig von einer Bedingung:
%[1 < 2 ? "true" : "false"]
Versionen vergleichen; zu 1 (wahr) oder 0 (falsch) expandieren:
%[ v"3.1.0-1" < v"1.0~alpha-2" ? 1 : 0]
Zu 1 expandieren, falls %aa zu 5 expandiert, anderenfalls zu 2 expandieren:
%[ "%{aa}" == "5" ? 1 : 2]
DEBUGGING¶
Einige nützliche Werkzeuge zum Arbeiten mit Makros und zur Fehlerbehebung:
rpm --eval "WERT"
rpm --define "aa 11" --eval "%aa"
rpm --eval "%global unamer %(uname -r)" --eval "%{macrobody:unamer}"
rpm --eval "%define unamer %(uname -r)" --eval "%{macrobody:unamer}"
rpmlua
rpmlua -e 'print(macros.defined("_libdir"))'
rpmspec --shell
rpmspec --shell telnet.spec
SIEHE AUCH¶
rpm(8), rpm-common(8), rpm-macrofile(5), rpm-config(5), rpm-lua(7), rpmspec(1), rpmlua(1)
ÜBERSETZUNG¶
Die deutsche Übersetzung dieser Handbuchseite wurde von Mario Blättermann <mario.blaettermann@gmail.com> erstellt.
Diese Übersetzung ist Freie Dokumentation; lesen Sie die GNU General Public License Version 3 oder neuer bezüglich der Copyright-Bedingungen. Es wird KEINE HAFTUNG übernommen.
Wenn Sie Fehler in der Übersetzung dieser Handbuchseite finden, schicken Sie bitte eine E-Mail an die Mailingliste der Übersetzer: debian-l10n-german@lists.debian.org.
| 7. November 2025 | RPM 6.0.0 |