Come posso usare la sintassi di Bash nei target di Makefile?


209

Trovo spesso molto utile la sintassi di Bash , ad esempio la sostituzione del processo come in diff <(sort file1) <(sort file2).

È possibile utilizzare tali comandi Bash in un Makefile? Sto pensando a qualcosa del genere:

file-differences:
    diff <(sort file1) <(sort file2) > $@

Nel mio GNU Make 3.80 questo darà un errore poiché usa shellinvece di basheseguire i comandi.


Questo era esattamente il mio problema, mi ci è voluto almeno un'ora per trovare questa domanda! Lascio qui il mio messaggio di errore in modo che i futuri lettori possano trovarlo: /bin/sh: -c: line 0: syntax error near unexpected token (''
David

Risposte:


381

Dalla documentazione di GNU Make,

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.

Quindi mettiti SHELL := /bin/bashin cima al tuo makefile e dovresti essere bravo ad andare.

A proposito: puoi anche farlo per un target, almeno per GNU Make. Ogni target può avere le proprie assegnazioni di variabili, in questo modo:

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"

Che stamperà:

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

Vedere "Valori variabili specifici del target" nella documentazione per maggiori dettagli. Quella linea può andare ovunque nel Makefile, non deve essere immediatamente prima del bersaglio.


43
500 taglie in attesa di un preventivo da man. Parli dei tempi. : P
Siddhartha

3
@inLoveWithPython Beh, in inforealtà, ma, credo che abbia aiutato davvero Andy. So di aver avuto giorni del genere ...
Derobert il

3
in caso di dubbio, @derobert intendeva letteralmente: SHELL=/bin/bashcome la prima riga del Makefile (o subito dopo il commento).
Yauhen Yakimovich,

1
Grazie @derobert ha risolto il mio problema in stackoverflow.com/questions/26806832/…
Chandan Choudhury il

2
È possibile cambiare la variabile SHELL solo per un particolare target di make ma lasciare intatti gli altri?
antred

18

Puoi chiamare bashdirettamente, usa il -cflag:

bash -c "diff <(sort file1) <(sort file2) > $@"

Naturalmente, potresti non essere in grado di reindirizzare alla variabile $ @, ma quando ho provato a farlo, ho ricevuto -bash: $@: ambiguous redirectun messaggio di errore, quindi potresti voler esaminare questo prima di entrare anche in questo (anche se sono usando bash 3.2.qualcosa, quindi forse il tuo funziona diversamente).


4

Se la portabilità è importante, potresti non voler dipendere da una shell specifica nel tuo Makefile. Non tutti gli ambienti hanno bash disponibile.


4

Puoi chiamare bash direttamente nel tuo Makefile invece di usare la shell predefinita:

bash -c "ls -al"

invece di:

ls -al

1
Si noti che makeignora il valore della variabile di ambiente SHELL.
Choroba,

2

C'è un modo per farlo senza impostare esplicitamente la variabile SHELL in modo che punti a bash. Questo può essere utile se hai molti makefile poiché SHELL non è ereditato dai makefile successivi o preso dall'ambiente. Devi anche essere sicuro che chiunque compili il tuo codice configura il proprio sistema in questo modo.

Se si esegue sudo dpkg-reconfigure dashe si risponde "no" al prompt, il sistema non utilizzerà dash come shell predefinita. Quindi punterà a bash (almeno in Ubuntu). Nota che usare dash come shell di sistema è un po 'più efficiente.


1
Quando viene invocato con il nome sh, bash viene eseguito in modalità compatibilità ( set -o posix). La funzionalità che l'OP sta tentando di utilizzare, la sostituzione del processo, non è disponibile in questa modalità.
Charles Duffy,

1

Un modo che funziona anche è metterlo in questo modo nella prima riga del tuo obiettivo:

your-target: $(eval SHELL:=/bin/bash)
    @echo "here shell is $$0"
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.