Estou tentando entender por que alguns Makefiles possuem pré-requisitos with %.txt
e 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 .c
vez 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 .c
arquivo aleatório , digamos foo.c
, e compile-o em um programa foo
que 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.