Estoy tratando de entender por qué algunos Makefiles tienen requisitos previos %.txt
y otros tienen *.txt
.
He creado este diseño de carpeta.
$ tree .
.
├── hi1.txt
├── hi2.txt
├── hi3.txt
└── Makefile
Primero, probé esto.
foo.txt: *.txt
echo $^
Y hace lo que espero.
$ make
echo hi1.txt hi2.txt hi3.txt
hi1.txt hi2.txt hi3.txt
Pero luego he visto que algunos Makefiles se utilizan %.txt
como comodín. Entonces lo intenté a continuación.
foo.txt: %.txt
echo $^
Sin embargo, esto produce un error.
$ make
make: *** No rule to make target '%.txt', needed by 'foo.txt'. Stop.
¿Alguien puede explicar por qué sucede esto?
GNU hace 4.3
Respuesta1
En make
, el signo de porcentaje se utiliza para la coincidencia de patrones y requiere uno en el objetivo y (al menos) uno en los requisitos previos:
%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
Con este archivo MAKE, especificamos que para construir algo cuyo nombre de archivo termine en .o
, necesita tener un archivo que tenga el mismo prefijo, pero que luego termine en .c
en lugar de.o
Para poder construir esas reglas, obviamente es necesario poder hacer referencia tanto al objetivo como a los requisitos previos; aquí es donde entran en juego las variables $@
y . significa "el objetivo de esta regla" y significa "el primer requisito previo enumerado de esta regla". Si necesita construir un comando que use$<
$@
$<
todorequisitos previos (por ejemplo, para vincular un ejecutable), entonces puede usar la variable $^
:
%: %.o lib.o
$(CC) $(LDFLAGS) -o $@ $^
Si combina los dos fragmentos de archivos MAKE de ejemplo anteriores en un archivo MAKE y tiene un archivo 'lib.c' con algún código común que desea usar en varios programas C en ese mismo directorio, entonces puede agregar cualquier .c
archivo aleatorio. , digamos foo.c
, y compílelo en un programa foo
que también enlace el código en lib.c
, sin requerir ningún cambio en su archivo MAKE.
Tenga en cuenta que también es posible tener patrones con el mismo objetivo, siempre que los requisitos previos sean diferentes; por ejemplo, lo siguiente funcionará:
%.o: %.c
$(CC).....
%.o: %.cpp
$(CXX).....
es decir, funcionará como se espera siempre y cuando no tenga ningún archivo fuente de C++ en este directorio que tenga el mismo nombre (sin extensión) que un archivo fuente de C. Si ese fuera el caso, la versión C++ se ignorará y en su lugar se compilará la fuente C (porque la regla C aparece primero en el archivo MAKE)
Para obtener más información, consulte elsección relevanteen el manual de creación de GNU.