Substituição de processo em GNU Makefiles

Substituição de processo em GNU Makefiles

Em um prompt bash, pode-se executar diff usando pseudoarquivos:

diff <(echo test) <(echo test)

Adicionar isso como está em um Makefile falha:

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

O erro (dica: /bin/sh aponta para /bin/bash neste sistema):

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

O que isso significa e ainda existe uma maneira de diferenciar duas saídas sem usar arquivos temporários?

Responder1

/bin/shpode estar bashno seu sistema, mas quando invocado como sh, bashestará rodando no modo POSIX (como se POSIXLY_CORRECTtivesse sido definido ou iniciado com --posix).

Neste modo, não existem substituições de processo.

Soluções:

  1. Use arquivos temporários explícitos:

    all:
        command1 >tmpfile
        command2 | diff tmpfile -
        rm -f tmpfile
    
  2. Use um bash -cscript em linha:

    all:
        bash -c 'diff <(command1) <(command2)'
    
  3. Defina a variável Makefile SHELLcomo /bin/bash(ou qualquer que seja o caminho bashem seu sistema):

    SHELL=/bin/bash
    

Se você deseja portabilidade, escolha a primeira solução. Se você concorda com a dependência de bash, escolha a segunda. Se você também não precisa se preocupar com makeimplementações não-GNU, use o terceiro.


Em relação à configuração SHELL: O padrão POSIX diz que os executáveis ​​em Makefiles devem ser invocados com a system()função da biblioteca C por make. Não é garantido que esta função use a SHELLvariável de ambiente (na verdade, fazer isso é desencorajado pelo padrão). O padrão também vai longe ao dizer que definir a variável Makefile SHELLnão deve afetar ovariável de ambiente SHELL. Na maioria das implementações makeque conheço, entretanto, a variável Makefile SHELLserá usada para executar os comandos.

A sugestão ema justificativa para a makeutilidadeé usar bash -c:

O recurso histórico MAKESHELLe os recursos relacionados fornecidos por outras makeimplementações foram omitidos. Em algumas implementações, é usado para permitir que um usuário substitua o shell a ser usado para executar makecomandos. Isso foi confuso; para um portátil make, o shell deve ser escolhido pelo gravador do makefile. Além disso, um gravador de makefile não pode exigir o uso de um shell alternativo e ainda considerar o makefile portátil. Embora fosse possível padronizar um mecanismo para especificar um shell alternativo, as implementações existentes não concordam com tal mecanismo, e os criadores de makefile já podem invocar um shell alternativo especificando o nome do shell na regra para um destino; por exemplo:

python -c "foo"

informação relacionada