19 Stimmen

Shell-Statuscodes in Make

Ich verwende ein Makefile (mit GNU make unter Linux), um meine Routinearbeit beim Refactoring eines Python-Skripts zu automatisieren. Das Skript erstellt eine Ausgabedatei, und ich möchte sicherstellen, dass die Ausgabedatei bei meinen Refactorings unverändert bleibt.

Ich habe jedoch keinen Weg gefunden, den Statuscode eines Befehls so zu nutzen, dass er sich auf einen nachfolgenden Shell-Befehl auswirkt.

Die folgende Regel verdeutlicht das Problem:

check-cond-codes:
    diff report2008_4.csv report2008_4.csv-save-for-regression-testing; echo no differences: =$$!=
    diff -q poalim report2008_4.csv; echo differences: =$$!=

Der erste 'diff' vergleicht zwei gleiche Dateien, und der zweite vergleicht zwei verschiedene Dateien. Die Ausgabe ist:

diff report2008_4.csv report2008_4.csv-save-for-regression-testing; echo no differences: =$!=
no differences: ==
diff -q poalim report2008_4.csv; echo differences: =$!=
Files poalim and report2008_4.csv differ
differences: ==

Offensichtlich ist '$$!' die falsche Variable, um den Statuscode von 'diff' zu erfassen. Selbst die Verwendung von SHELL := /bin/bash am Anfang des Makefiles hat das Problem nicht gelöst.

Eine Variable, die den Wert zurückgibt, den ich benötige, würde (falls sie überhaupt existiert) in einem 'if'-Befehl in der eigentlichen Regel verwendet werden.

Die Alternative, ein kleines Ad-hoc-Shell-Skript anstelle des Schreibens aller Befehle direkt im Makefile zu erstellen, ist unerwünscht, aber ich werde sie als letzten Ausweg nutzen.

Verwandt:

0 Stimmen

Ich glaube, du suchst die Variable .SHELLSTATUS: Wie man den Exit-Status eines Shell-Befehls in einem GNU Makefile erhält?

38voto

Eric Melski Punkte 15572

Ich denke, du suchst die $? Shell-Variable, die den Exit-Code des vorherigen Befehls angibt. Zum Beispiel:

$ diff foo.txt foo.txt
$ echo $?
0

Um dies in deiner makefile zu verwenden, musst du das $ escapen, wie in $$?:

all:
    diff foo.txt foo.txt ; if [ $$? -eq 0 ] ; then echo "keine Unterschiede" ; fi

Beachte, dass jeder Befehl im Regelkörper von make in einem separaten Subshell ausgeführt wird. Zum Beispiel funktioniert das Folgende nicht:

all:
    diff foo.txt foo.txt
    if [ $$? -eq 0 ] ; then echo "keine Unterschiede" ; fi

Weil die Befehle diff und if in verschiedenen Shell-Prozessen ausgeführt werden. Wenn du den Ausgabe-Status des Befehls verwenden möchtest, musst du dies im Kontext derselben Shell tun, wie in meinem vorherigen Beispiel.

4voto

Omer Zak Punkte 1119

Verwenden Sie '$$?' anstelle von '$$!' (dank der 4. Antwort von Exit Shell Script Based on Process Exit Code)

4voto

Rob Wells Punkte 35303

Vergessen Sie nicht, dass jeder Ihrer Befehle in separaten Unter-Shell ausgeführt wird.

Deshalb sehen Sie sehr oft etwas Ähnliches wie:

my_target:
    mache etwas \
    mache etwas anderes \
    mache letzte Sache.

Und beim Debuggen vergessen Sie nicht die sehr hilfreiche -n Option, die die Befehle ausdruckt, aber nicht ausführt, und die -p Option, die Ihnen die komplette Make-Umgebung zeigt, einschließlich wo die verschiedenen Bestandteile gesetzt wurden.

HTH

Viele Grüße,

2voto

Timothy Gu Punkte 3287

Wenn Sie den Ergebniscode an ein if übergeben, könnten Sie einfach Folgendes tun:

all:
    if diff foo.txt foo.txt ; then echo "keine Unterschiede" ; fi

0voto

David Z Punkte 121773

Die Bash-Variable ist $?, aber warum möchten Sie den Statuscode sowieso ausgeben?

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X