¿Cómo puedo usar la sintaxis Bash en los destinos Makefile?


A menudo encuentro que la sintaxis de Bash es muy útil, por ejemplo, la sustitución de procesos como en diff <(sort file1) <(sort file2).

¿Es posible usar estos comandos Bash en un Makefile? Estoy pensando en algo como esto:

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

En mi GNU Make 3.80 esto dará un error ya que usa shell en lugar de bash para ejecutar los comandos.

Author: Peter Mortensen, 2009-02-26

5 answers

De la documentación de 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.

Así que pon SHELL := /bin/bash en la parte superior de tu makefile, y deberías estar listo.

Por cierto: También puede hacer esto para un objetivo, al menos para GNU Make. Cada destino puede tener sus propias asignaciones de variables, así:

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"

Que va a imprimir:

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

Consulte "Valores de variables específicas de destino" en la documentación para obtener más detalles. Esa línea puede ir a cualquier parte del Makefile, no tiene que estar inmediatamente antes del destino.

 298
Author: derobert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-04 16:10:32

Puede llamar a bash directamente, use la bandera -c:

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

Por supuesto, es posible que no pueda redirigir a la variable@@, pero cuando traté de hacer esto, recibí -bash: $@: ambiguous redirect como un mensaje de error, por lo que es posible que desee mirar eso antes de entrar también en esto (aunque estoy usando bash 3.2.algo, así que tal vez el tuyo funciona de manera diferente).

 12
Author: Chris Lutz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-26 06:03:31

Si la portabilidad es importante, es posible que no desee depender de un shell específico en su Makefile. No todos los entornos tienen bash disponible.

 3
Author: Menno Smits,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-11-19 12:34:25

Puede llamar a bash directamente dentro de su Makefile en lugar de usar el shell predeterminado:

bash -c "ls -al"

En lugar de:

ls -al
 3
Author: paxdiablo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-12 21:54:00

Hay una manera de hacer esto sin establecer explícitamente su variable SHELL para que apunte a bash. Esto puede ser útil si tiene muchos makefiles ya que el SHELL no es heredado por makefiles posteriores o tomado del entorno. También debe asegurarse de que cualquiera que compile su código configure su sistema de esta manera.

Si ejecuta sudo dpkg-reconfigure dash y responde 'no' al mensaje, su sistema no usará dash como shell predeterminado. Entonces apuntará a bash (al menos en Ubuntu). Tenga en cuenta que el uso dash como su shell del sistema es un poco más eficiente sin embargo.

 1
Author: Bill G,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-14 17:03:26