make(1)
em si não sabe como executar os comandos do shell. Poderia ter sido feito para isso, mas o Unix Way é ter preocupações bem separadas: make(1)
sabe como construir gráficos de dependência que determinam o que deve ser feito, e sh(1)
sabe como executar comandos.
O ponto que o autor está tentando fazer é que você não deve escrever essas linhas de comando, de modo que uma mais tarde dependa de uma anterior, exceto através do sistema de arquivos. Por exemplo, isso não funcionará:
sometarget: some.x list.y of-dependencies.z
foo='run-some-command-here'
run-some-other-command $$foo
Se este fosse um script de shell de duas linhas, a saída do primeiro comando seria passada como um argumento para o segundo comando. Mas como cada um desses comandos é executado em um sub-shell separado, o valor da variável $foo
é perdido após o primeiro sub-shell existir, portanto, não há nada para passar para o primeiro.
Uma maneira de contornar isso, como sugerido acima, é usar o sistema de arquivos:
TMPDIR=/tmp
TMPFILE=$(TMPDIR)/example.tmp
sometarget: some.x list.y of-dependencies.z
run-some-command-here > $(TMPFILE)
run-some-other-command 'cat $(TMPFILE)'
Isso armazena a saída do primeiro comando em um local persistente para que o segundo comando possa carregar o valor.
Outra coisa que tropeça make(1)
newbies algumas vezes é que construções que geralmente são divididas em várias linhas para legibilidade em um script de shell devem ser escritas em uma única linha ou agrupadas em um script de shell externo quando você as executa em Makefile
. Loops são um bom exemplo; isso não funciona:
someutilitytarget:
for f in *.c
do
munch-on $f
done
Você precisa usar ponto e vírgula para obter tudo em uma única linha:
someutilitytarget:
for f in *.c ; do munch-on $f ; done
Para mim, sempre que isso me fornece uma linha de comando com mais de 80 caracteres, movo-a para um script de shell externo para que seja legível.