Por que se comportar de maneira estranha ao escrever vários destinos usando o caractere%?

3

De acordo com o Manual GNU Make

A rule with multiple targets is equivalent to writing many rules, each with one target, and all identical aside from that. The same recipe applies to all the targets, but its effect may vary because you can substitute the actual target name into the recipe using ‘$@’. The rule contributes the same prerequisites to all the targets also.

Este é meu primeiro Makefile:

%.in %.out:
    echo BLANK > $@

E esta é minha primeira sessão de bash:

$ ls
Makefile

$ make a.in a.out
echo BLANK > a.in
make: Nothing to be done for 'a.out'.

$ ls
Makefile  a.in

$ make a.out
echo BLANK > a.out

$ ls
Makefile  a.in  a.out

$ make b.in c.out
echo BLANK > b.in
echo BLANK > c.out

$ make d.in d.out
echo BLANK > d.in
make: Nothing to be done for 'd.out'.

$ make e.out e.in
echo BLANK > e.out
make: Nothing to be done for 'e.in'.

$ ls
Makefile  a.in  a.out  b.in  c.out  d.in  e.out

Este é o meu segundo Makefile:

%.in:
    echo BLANK > $@

%.out:
    echo BLANK > $@

E esta é a sessão bash correspondente:

$ ls
Makefile

$ make a.in a.out
echo BLANK > a.in
echo BLANK > a.out

$ ls
Makefile  a.in  a.out

$ # nice       

Por que o primeiro Makefile não cria alvos como <name>.in <same name>.out simultaneamente? Por que não é interpretado de forma semelhante ao segundo Makefile?

    
por belkka 26.08.2017 / 16:47

1 resposta

2

Você não deve ter vários destinos implícitos em uma única regra. Não me lembro se isso é declarado em qualquer lugar, mas regras como essa são certamente más práticas. Aqui está o que está acontecendo:

$ cat Makefile 
%.in %.out :
        echo BLANK > $@

$ make -d a.in a.out
[... irrelevant output skipped ...]
Updating goal targets....
Considering target file 'a.in'.
 File 'a.in' does not exist.
 Looking for an implicit rule for 'a.in'.
 Trying pattern rule with stem 'a'.
 Found an implicit rule for 'a.in'.
 Finished prerequisites of target file 'a.in'.
Must remake target 'a.in'.
echo BLANK > a.in
Successfully remade target file 'a.in'.
Considering target file 'a.out'.
File 'a.out' was considered already.
make: Nothing to be done for 'a.out'.

Anote as linhas:

Considering target file 'a.out'.
File 'a.out' was considered already.

Alvos implícitos não "existem" até que sejam tentados e, portanto, a regra não é "dividida" em várias regras. Quando a.in é tentado e correspondido com sucesso, todos os outros alvos são marcados como tentados. A grande maioria do tempo isso não é o que você quer. Apenas escreva duas regras.

    
por 26.08.2017 / 18:11

Tags