Makefile e .ONESHELL

4

Quando .ONESHELL não é usado, o Makefile executa cada comando do shell em um shell separado. Qual é o benefício disso? Por que o makefile não usa o mesmo shell?

    
por Nikhil 17.10.2018 / 10:50

2 respostas

7

Uma razão é que uma falha em um dos comandos de receita não seria detectada pelo GNU make . Apenas o status final de saída do shell seria dado a make . Teria que definir adicionalmente .SHELLFLAGS para -e para fazer com que o shell terminasse logo no início dos erros (isso é necessário para chamadas de shell multi-comando mesmo sem .ONESHELL se eles precisarem falharem em o primeiro erro).

Tudo isso é bom para quando SHELL é um shell POSIX. Um Makefile também pode definir SHELL como, por exemplo /usr/bin/perl ou algum outro interpretador de comandos. Pode então ser apropriado, ou não, usar .ONESHELL .

Tornar .ONESHELL o comportamento padrão em make poderia potencialmente quebrar Makefiles antigos.

Mesmo que esta não seja uma questão relacionada ao padrão POSIX ou a conformidade com esse padrão pelo GNU make , a Justificativa de a especificação POSIX para make tem a dizer sobre o problema em questão:

The default in some advanced versions of make is to group all the command lines for a target and execute them using a single shell invocation; the System V method is to pass each line individually to a separate shell. The single-shell method has the advantages in performance and the lack of a requirement for many continued lines. However, converting to this newer method has caused portability problems with many historical makefiles, so the behavior with the POSIX makefile is specified to be the same as that of System V. It is suggested that the special target .ONESHELL be used as an implementation extension to achieve the single-shell grouping for a target or group of targets.

O GNU make é compatível com POSIX a esse respeito, pois implementa o comportamento do System V e fornece um .ONESHELL de destino para ativar o comportamento alternativo, se desejado. ... o que é outro motivo para o GNU make manter o comportamento atual.

    
por 17.10.2018 / 11:05
2

.ONESHELL é uma extensão específica do fornecedor GNU que não é portátil e não faz parte do padrão POSIX.

A razão pela qual isso não está no padrão POSIX é mais provável que haja apenas uma implementação que ofereça suporte a ele.

A razão pela qual este não é o padrão padrão é mais fácil de explicar:

POSIX tries to standardize existing behavior and POSIX does not like to make existing original UNIX implementations being in conflict with the standard - except when a specific behavior can be seen as a clear design bug.

A implementação original de make de Stuart Feldman em 1977 chamou cada linha da lista de ações em um shell separado usando sh -ce cmdline e isso se tornou o mestre para todas as implementações posteriores de make .

Mas mesmo a implementação GNU (vista separadamente) não é isenta de problemas quando .ONESHELL está em vigor. A razão é que o GNU make não configura o -e do shell ao invocar comandos. Isso faz com que um script de shell de várias linhas causado por .ONESHELL não seja finalizado quando ocorrer um erro.

Além disso, vejo poucos benefícios para .ONESHELL :

  • Scripts de shell de várias linhas podem ser usados dentro de make por uma sequência de nova linha de barra invertida nos arquivos de criação.

  • O argumento de desempenho não se aplica às implementações modernas do make , uma vez que as implementações modernas tentam evitar chamar o shell caso a linha de comando não contenha meta-caracteres específicos do shell.

  • Minha implementação de smake até implementa o suporte sequencial para o comando echo , no caso de ser o primeiro comando em uma linha, echo seguido por um ponto-e-vírgula e um outro comando simples. Isso evita a necessidade de chamar o shell por mais de 90% dos casos.

por 17.10.2018 / 12:42

Tags