Não pare de fabricar se um comando falhar, mas verifique o status da saída

22

Estou tentando instruir o GNU Make 3.81 a não parar se um comando falhar (então prefixo o comando -), mas também quero verificar o status de saída no próximo comando e imprimir uma mensagem mais informativa. No entanto, meu Makefile abaixo falha:

$ cat Makefile 
all:
    -/bin/false
    ([ $$? -eq 0 ] && echo "success!") || echo "failure!"
$
$ make
/bin/false
make: [all] Error 1 (ignored)
([ $? -eq 0 ] && echo "success!") || echo "failure!"
success!

Por que o Makefile acima ecoa "sucesso!" em vez de "fracasso!" ?

atualizar:

Seguindo e expandindo a resposta aceita, abaixo está como ela deve ser escrita:

failure:                                                                                                                                                                                                                                      
    @-/bin/false && ([ $$? -eq 0 ] && echo "success!") || echo "failure!"                                                                                                                                                                 
success:                                                                                                                                                                                                                                      
    @-/bin/true && ([ $$? -eq 0 ] && echo "success!") || echo "failure!"     
Marcus Junius Brutus
fonte
2
Você pode querer investigar a .ONESHELL:diretiva.
22815 Jonathan
.ONESHELL executará todos os blocos de recebimento em um shell que tenha efeito: se o primeiro comando falhar, os próximos serão executados sem problemas. Para evitar que isso .SHELLFLAGS = -ecdeva ser usado. Mas, neste caso, você não pode usar -mais o prefixo (para comando pessoal do recibo) porque o make escreverá que o erro é ignorado, mas ainda falhará em todo o bloco. Então, essa || :é a solução para ignorar o comando. Mas não é multiplataforma (o Windows não tem || :ou || true)
Paul-AG

Respostas:

14

Cada comando de atualização em uma regra Makefile é executado em um shell separado. Então $? não contém o status de saída do comando com falha anterior, contém o valor padrão para $? em uma nova concha. É por isso que seu [$? -eq 0] sempre é bem-sucedido.

Kyle Jones
fonte
10

Você não precisa do teste de, $?pois &&funciona se $?for zero e ||prosseguir no caso de um valor de retorno diferente de zero.

E você não precisa do menos, pois o valor de retorno a ser obtido é obtido na última chamada do programa de prosseguimento da linha. Então, isso funciona bem

falha:

      @/bin/false && echo "success!" || echo "failure!" 

sucesso:

      @/bin/true && echo "success!" || echo "failure!"

O oposto acontece: se você quiser fazer sua própria mensagem e quiser interromper o processo de criação de qualquer maneira com um valor diferente de zero, precisará escrever algo como isto:

falha:

      @/bin/false && echo "success!" || { echo "failure!"; exit 1; }
Andreas
fonte
8

A partir da documentação make GNU :

Quando os erros devem ser ignorados, por causa de um sinalizador '-' ou '-i', faça com que os deleites retornem como um sucesso , exceto que ele imprime uma mensagem que informa o código de status com o qual o shell saiu e diz que o erro foi ignorado.

Para utilizar makeo status de saída de um caso como este, execute a makepartir de um script:

#!/bin/bash
make
([ $? -eq 0 ] && echo "success!") || echo "failure!"

E faça com que seu Makefile contenha:

all:
    /bin/false
Timothy Martin
fonte