2009-02-26 4 views
143

Ich finde häufig Bash Syntax sehr hilfreich, z. Prozesssubstitution wie in diff <(sort file1) <(sort file2).Wie kann ich die Bash-Syntax in Makefile-Zielen verwenden?

Ist es möglich, solche Bash-Befehle in einem Makefile zu verwenden? Ich denke an so etwas wie dieses:

file-differences: 
    diff <(sort file1) <(sort file2) > [email protected] 

In meinem GNU 3.80 Machen Sie dieses einen Fehler geben, da es die shell statt bash verwendet die Befehle auszuführen.

Antwort

258

Von der GNU Make Dokumentation,

5.3.1 Choosing the Shell 
------------------------ 

The program used as the shell is taken from the variable `SHELL'. If 
this variable is not set in your makefile, the program `/bin/sh' is 
used as the shell. 

setzte So SHELL := /bin/bash an der Spitze Ihrer Make-Datei, und Sie sollten gut zu gehen.

BTW: Sie können dies auch für ein Ziel tun, zumindest für GNU Make. Jedes Ziel kann seine eigene Variablenzuweisungen haben, wie folgt aus:

all: a b 

a: 
    @echo "a is $$0" 

b: SHELL:=/bin/bash # HERE: this is setting the shell for b only 
b: 
    @echo "b is $$0" 

Das wird Druck:

a is /bin/sh 
b is /bin/bash 

Siehe "Target-spezifische Variablenwerte" in der Dokumentation für weitere Details. Diese Linie kann überall im Makefile liegen, sie muss nicht unmittelbar vor dem Ziel sein.

+21

500 Bounty warten auf ein Zitat von 'man'. Sprechen Sie über Timings. : P – SiddharthaRT

+3

@inLoveWithPython Nun, 'Info', eigentlich, aber, ich denke, es hat Andy wirklich geholfen. Ich weiß, ich hatte Tage wie diese ... – derobert

+2

im Zweifel bedeutete @derobert wörtlich: 'SHELL =/bin/bash' als die erste Zeile des Makefiles (oder direkt nach dem Kommentar). –

10

können Sie bash direkt aufrufen, verwenden Sie die -c Flagge:

bash -c "diff <(sort file1) <(sort file2) > [email protected]" 

Natürlich können Sie nicht in der Lage sein kann, auf die Variable $ @ zu umleiten, aber wenn ich versucht, dies zu tun, ich habe -bash: [email protected]: ambiguous redirect als eine Fehlermeldung, also sollten Sie sich das genauer ansehen, bevor Sie sich damit beschäftigen (obwohl ich bash 3.2.something verwende, also funktioniert vielleicht Ihre anders).

2

Sie können bash rufen direkt in Ihrem Makefile stattdessen die Standard-Shell verwenden:

bash -c "ls -al" 

statt:

ls -al 
+0

Beachten Sie, dass 'make' den Wert der Umgebungsvariablen SHELL ignoriert. – choroba

4

Wenn Portabilität wichtig ist, können Sie nicht auf eine bestimmte Schale abhängen wollen in deinem Makefile. Nicht in allen Umgebungen ist Bash verfügbar.

1

Es gibt eine Möglichkeit, dies zu tun, ohne Ihre SHELL-Variable explizit auf bash zu setzen. Dies kann nützlich sein, wenn Sie viele Makefiles haben, da SHELL nicht von nachfolgenden Makefiles vererbt oder aus der Umgebung übernommen wird. Sie müssen auch sicher sein, dass jeder, der Ihren Code kompiliert, sein System auf diese Weise konfiguriert.

Wenn Sie sudo dpkg-reconfigure dash ausführen und mit der Eingabeaufforderung 'no' antworten, verwendet das System nicht das Dash als Standard-Shell. Es wird dann auf bash (zumindest in Ubuntu) zeigen. Beachten Sie, dass die Verwendung von Bindestrich als System-Shell ein wenig effizienter ist.

+1

Wenn bash unter dem Namen 'sh' aufgerufen wird, läuft bash im Kompatibilitätsmodus (' set -o posix'). Die Funktionalität, die das OP zu verwenden versucht, die Prozesssubstitution, ist in diesem Modus nicht verfügbar. –