Prozesssubstitution in GNU Makefiles

Prozesssubstitution in GNU Makefiles

In einer Bash-Eingabeaufforderung kann man „diff“ mithilfe von Pseudodateien ausführen:

diff <(echo test) <(echo test)

Das Hinzufügen in dieser Form zu einem Makefile schlägt fehl:

all:
        diff <(echo test) <(echo test)

Der Fehler (Hinweis: /bin/sh verweist auf diesem System auf /bin/bash):

/bin/sh: -c: line 0: syntax error near unexpected token `('
/bin/sh: -c: line 0: `diff <(echo test) <(echo test)'

Was bedeutet das und gibt es eine Möglichkeit, zwei Ausgaben dennoch zu vergleichen, ohne temporäre Dateien zu verwenden?

Antwort1

/bin/shbefindet sich möglicherweise bashauf Ihrem System, wird aber beim Aufruf als shim bashPOSIX-Modus ausgeführt (als ob POSIXLY_CORRECTes definiert oder mit gestartet worden wäre --posix).

In diesem Modus gibt es keine Prozessersetzungen.

Lösungen:

  1. Verwenden Sie explizite temporäre Dateien:

    all:
        command1 >tmpfile
        command2 | diff tmpfile -
        rm -f tmpfile
    
  2. Verwenden Sie ein bash -cInline-Skript:

    all:
        bash -c 'diff <(command1) <(command2)'
    
  3. Definieren Sie die Makefile-Variable SHELLwie folgt /bin/bash(oder entsprechend dem Pfad bashauf Ihrem System):

    SHELL=/bin/bash
    

Wenn Sie Portabilität wünschen, wählen Sie die erste Lösung. Wenn Sie mit einer Abhängigkeit von einverstanden sind bash, wählen Sie die zweite. Wenn Sie sich außerdem nicht um Nicht-GNU- makeImplementierungen kümmern müssen, verwenden Sie die dritte.


Bezüglich des Setzens : Der POSIX-Standard besagt, dass ausführbare Dateien in Makefiles mit der C-Bibliotheksfunktion by SHELLaufgerufen werden sollten . Es gibt keine Garantie dafür, dass diese Funktion die Umgebungsvariable verwendet (tatsächlich wird dies vom Standard nicht empfohlen). Der Standard geht auch ausführlich darauf ein, dass das Setzen der Makefile-Variable keinen Einfluss auf diesystem()makeSHELLSHELLUmgebungsvariable SHELLmake. In den meisten mir bekannten Implementierungen SHELLwird jedoch die Makefile-Variable zum Ausführen der Befehle verwendet.

Der Vorschlag indie Begründung für den makeNutzenist zu verwenden bash -c:

Das historische MAKESHELLFeature und verwandte Features anderer makeImplementierungen wurden weggelassen. In einigen Implementierungen wird es verwendet, um einem Benutzer zu ermöglichen, die Shell zu überschreiben, die zum Ausführen von makeBefehlen verwendet werden soll. Das war verwirrend; für ein portables makesollte die Shell vom Makefile-Autor ausgewählt werden. Außerdem kann ein Makefile-Autor nicht die Verwendung einer alternativen Shell verlangen und das Makefile trotzdem als portabel betrachten. Obwohl es möglich wäre, einen Mechanismus zum Angeben einer alternativen Shell zu standardisieren, sind sich vorhandene Implementierungen nicht über einen solchen Mechanismus einig, und Makefile-Autoren können bereits eine alternative Shell aufrufen, indem sie den Shell-Namen in der Regel für ein Ziel angeben; zum Beispiel:

python -c "foo"

verwandte Informationen