Qual é a diferença entre o pré-requisito do makefile de porcentagem e asterisco (estrela)

Qual é a diferença entre o pré-requisito do makefile de porcentagem e asterisco (estrela)

Estou tentando entender por que alguns Makefiles possuem pré-requisitos with %.txte outros possuem *.txt.

Eu criei este layout de pasta.

$ tree .
.
├── hi1.txt
├── hi2.txt
├── hi3.txt
└── Makefile

Primeiro, tentei isso.

foo.txt: *.txt
    echo $^

E faz o que eu espero.

$ make
echo hi1.txt hi2.txt hi3.txt
hi1.txt hi2.txt hi3.txt

Mas eu vi alguns Makefiles usados %.txt​​​​como curinga. Então tentei isso a seguir.

foo.txt: %.txt
    echo $^

No entanto, isso resulta em um erro.

$ make
make: *** No rule to make target '%.txt', needed by 'foo.txt'.  Stop.

Alguém pode explicar por que isso está acontecendo?

GNU Make 4.3

Responder1

No make, o sinal de porcentagem é usado para correspondência de padrões e requer um no destino, bem como (pelo menos) um nos pré-requisitos:

%.o: %.c
        $(CC) $(CFLAGS) -c -o $@ $<

Com este makefile, especificamos que para construir algo cujo nome de arquivo termine com .o, você precisa ter um arquivo que tenha o mesmo prefixo, mas termine com em .cvez de.o

Para poder construir essas regras, obviamente você precisa ser capaz de se referir ao alvo, bem como aos pré-requisitos; é aqui que entram as variáveis $@​​​​e . significa 'o alvo desta regra' e significa 'o primeiro pré-requisito listado desta regra'. Se você precisar construir um comando que use$<$@$<todospré-requisitos (por exemplo, para vincular um executável), então você pode usar a variável $^:

%: %.o lib.o
        $(CC) $(LDFLAGS) -o $@ $^

Se você combinar os dois trechos de makefile de exemplo acima em um makefile e tiver um arquivo 'lib.c' com algum código comum que deseja usar em vários programas C nesse mesmo diretório, poderá adicionar qualquer .carquivo aleatório , digamos foo.c, e compile-o em um programa fooque também vincule o código em lib.c, sem exigir nenhuma alteração em seu makefile.

Observe que também é possível ter padrões com o mesmo alvo, desde que os pré-requisitos sejam diferentes; por exemplo, o seguinte funcionará:

%.o: %.c
        $(CC).....
%.o: %.cpp
        $(CXX).....

isto é, ele funcionará conforme o esperado, desde que você não tenha nenhum arquivo de origem C++ neste diretório que tenha o mesmo nome (extensão sem extensão) de um arquivo de origem C. Se for esse o caso, a versão C++ será ignorada e a fonte C será compilada (porque a regra C é listada primeiro no makefile)

Para mais informações, consulte oseção relevanteno manual de criação do GNU.

informação relacionada