2010-06-22 11 views
12

Tengo el siguiente makefile recursiva:Al declarar la regla patrón tan falsa, no se desencadena

.PHONY: all clean 

%.subdir: 
    $(MAKE) -C src $* 
    $(MAKE) -C dict $* 

all: all.subdir 

clean: clean.subdir 

y trabaja muy bien:

$ make all 
make -C src all 
make[1]: Entering directory `/or-1.3.6-fix/src' 
make[1]: Nothing to be done for `all'. 
make[1]: Leaving directory `/or-1.3.6-fix/src' 
make -C dict all 
make[1]: Entering directory `/or-1.3.6-fix/dict' 
make[1]: Nothing to be done for `all'. 
make[1]: Leaving directory `/or-1.3.6-fix/dict' 

pero sería más lógico para definir %.subdir normas como falsa:

.PHONY: all clean all.subdir clean.subdir 

y ahora hacen paradas a trabajar como yo quiero:

$ make all 
make: Nothing to be done for `all'. 
$ make -d all 
... 
Updating goal targets.... 
Considering target file `all'. 
File `all' does not exist. 
    Considering target file `all.subdir'. 
    File `all.subdir' does not exist. 
    Finished prerequisites of target file `all.subdir'. 
    Must remake target `all.subdir'. 
    Successfully remade target file `all.subdir'. 
Finished prerequisites of target file `all'. 
Must remake target `all'. 
Successfully remade target file `all'. 
make: Nothing to be done for `all'. 

¿Alguien puede explicarme por qué (o incluso mejor me señalan para hacer la documentación)?

Respuesta

17

Tiene razón, tendría más sentido definir las reglas del subdirectorio como PHONY. Pero Make no tiene en cuenta las reglas implícitas para los objetivos PHONY, por lo que tendrá que volver a escribir esa regla. Sugiero lo siguiente:

SUBDIR_TARGETS = all.subdir clean.subdir 
.PHONY: all clean $(SUBDIR_TARGETS) 

$(SUBDIR_TARGETS): %.subdir: 
    $(MAKE) -C src $* 
    $(MAKE) -C dict $* 

all: all.subdir 
clean: clean.subdir 
+1

¡Gracias por la buena pista! Muy bien. Prefiero embellecerme un poco más y decir 'PHONY_TARGETS: = all clean' y luego' .PHONY: $ (PHONY_TARGETS) $ (addsuffix .subdir, $ (PHONY_TARGETS)) ' –

+1

Encontré la documentación para esos dos puntos buscando target/dep línea si alguien está interesado: https://www.gnu.org/software/make/manual/html_node/Static-Usage.html#Static-Usage – solstice333

7

Si está usando GNU make, ver the official Make manual

La marca no está haciendo nada, ya que no ve ningún archivo a hacer (ya que todos ellos son falsos). Asegúrese de que su valor predeterminado objetivo implícito no es falso, por lo que make tiene algo que construir.

Actualización: De this section del manual de make:

ya que sabe que los objetivos falsos no no nombrar los archivos reales que podrían ser rehecho de otros archivos, hacen saltos la búsqueda regla implícita de phony objetivos.

Por lo tanto, sus objetivos implícitos nunca se buscan porque son falsos.

se puede lograr lo que usted está tratando de hacer de otra manera. Pruebe esto:

SUBDIRS := all clean 
.PHONY: $(SUBDIRS) 

$(SUBDIRS): 
    echo $(MAKE) -C src [email protected] 
    echo $(MAKE) -C dict [email protected] 
+0

Gracias por la respuesta. He leído el documento, así que si me indica la cita exacta del documento, puedo calificar su respuesta. Más sobre su sugerencia sobre el objetivo predeterminado no falso es incorrecto. –

+0

La respuesta se ha actualizado con una sección específica sobre reglas falsas y objetivos implícitos, así como una forma alternativa de abordar el problema. – bta

+0

Gracias, ahora se ve mucho mejor. –

7

Eso GNU make objetivos requeridos declarados como .PHONY ser explícitos ya se ha dicho en las otras respuestas, que también proporcionan algún remedio a esto.

En esta respuesta adicional, me gustaría agregar una alterativa que como probé combina el comportamiento "falso", es decir, que los objetivos se activan cada vez que existen archivos con el mismo nombre (se ignoran). La alternativa es la siguiente:

.PHONY: phony_explicit 

phony_explicit: 

%.subdir: phony_explicit 
    $(MAKE) -C src $* 
    $(MAKE) -C dict $* 

Funciona en la premisa de que, si bien sólo los objetivos explícitos se pueden establecer como .PHONY, cualquiera que sea depende de un objetivo explícito, por lo tanto falsa es en sí heredar mucho (que yo sepa) todos los atributos falsos . Un objetivo implícito, es decir, coincidencia de patrones como el %.subdir anterior, es como si se estuviera agregando al .PHONY (lo cual es imposible porque no es explícito en sí mismo), pero se está convirtiendo en falso a través de su falso phony_explicit anterior a la aparición.

Se reduce que cada regla, también implícita mediante la coincidencia de patrones, que tiene en sus requisitos previos un destino falso explícito (es decir, un objetivo que se agrega al .PHONY) es a través de esta dependencia también ejecutada en un estilo falso (cada vez, incondicionalmente del sistema de archivos que tiene erróneamente un archivo con un nombre concomitante).

De hecho, el GNU Make documentación menciona la FORCEtarget, que en algunas versiones de GNU que no ofrecen un objetivo .PHONY emula en parte el comportamiento .PHONY. La alternativa presentada aquí usa esta aplicación de destino FORCE, pero debido a que se utiliza la marca GNU también establece el objetivo FORCE como .PHONY, evitando posibles conflictos con los archivos realmente existentes del mismo nombre.

Con esta solución incluso un

touch clean.subir; make clean.subdir 

cederá la invocación deseado de

make -C src clean 
make -C dist clean 

Lo que podría ser un posible punto a favor de esta alternativa es que no necesita ninguna declaración explícita de clean.subdir y all.subdir , pero realmente está usando la coincidencia de patrones implícita %.subdir.

Cuestiones relacionadas