tutorial make makefile gnu-make

makefile - tutorial - ¿Los requisitos previos de solo pedido no funcionan correctamente en GNU make?



makefile ubuntu (1)

¿Estoy entendiendo mal la forma en que funcionan los requisitos previos de orden solamente?

Sí, eso es lo que parece.

El nombre "solo por orden" es algo confuso. Los requisitos previos detrás de la | se denominan "requisitos previos de orden solamente" no porque cambien el orden de ejecución de la receta dentro de la lista de requisitos previos para un solo objetivo, sino porque su único propósito es tener ciertos objetivos creados antes que otros, como un bootstrap. Como lo explica el usuario bobbogo a continuación (- gracias por corregirlo): si make decide reconstruir un requisito previo de un objetivo, ejecutará la receta para ese requisito previo. Ahora, por un requisito previo ordinario, esta actualización implica que el objetivo ahora está desactualizado, y make tendrá que ejecutar la receta del objetivo. Por otro lado, para un requisito de solo pedido, make no marca el destino como que necesita una actualización.

Por ejemplo, consulte la sección Tipos de requisitos previos para un caso de uso donde se debe crear un directorio antes de que se creen los objetos en ese directorio.

Toma este ejemplo de makefile :

a: b touch a b: c touch b c: touch c x: | y touch x y: | z touch y z: touch z

Como puede ver, b y c son requisitos previos normales de a y b , mientras que y y z son requisitos previos de orden de x e y . Partiendo de una pizarra limpia, se ven iguales:

:~$ make a touch c touch b touch a :~$ make x touch z touch y touch x :~$ make a make: `a'' is up to date. :~$ make x make: `x'' is up to date.

Sin embargo, si ahora "actualizamos" manualmente los requisitos previos al final de la cadena ( z ), vemos la diferencia:

:~$ touch c :~$ make a touch b touch a :~$ touch z :~$ make x make: `x'' is up to date.

Esto muestra cómo los requisitos previos de solo pedido que existen no invalidan ningún objetivo, independientemente de su marca de tiempo. Sin embargo, la eliminación del destino solo de orden tiene como resultado la reconstrucción (pero solo la reconstrucción del archivo faltante):

:~$ rm c :~$ make a touch c touch b touch a :~$ rm z :~$ make x touch z

Dicho esto, la forma correcta de cambiar el orden en que se ejecutan sus recetas es mediante la corrección de las dependencias entre los objetivos. Por ejemplo, si desea que la primera se mefirst antes de la a , entonces necesita que mi mefirst requisito mefirst un requisito previo, como en

a: mefirst @echo a

No es posible dar la solución completa a su pregunta ya que no describió en detalle en qué orden espera que se ejecuten las recetas.

Hay un atajo a su respuesta que no es la solución, pero es interesante saberlo. Aunque no está documentado, parece que los requisitos previos de un solo objetivo se procesan en el orden en que aparecen. El | Signo no cambia eso. En su caso simple, puede aprovechar eso para lograr el resultado que está buscando:

normaltarget: mefirst2 normaltarget2 @echo "normaltarget done"

y

helloworld: mefirst normaltarget @echo "helloworld done"

Sin embargo, como lo señaló usted mismo, esta "solución" se rompe tan pronto como se usa la -j para ejecutar recetas en paralelo. Además, como lo señaló el usuario bobbogo, confiar en este mecanismo de pedido es una mala práctica. La introducción de nuevas dependencias puede interferir con el pedido. Así que no hagas esto :-)

Tengo un problema con los requisitos previos de orden solamente. Estos no se ejecutan primero en absoluto. ¿Estoy entendiendo mal la forma en que funcionan los requisitos previos de orden solamente?

El siguiente make script:

.PHONY: mefirst mefirst2 mefirst: @echo "I''m first!" mefirst2: @echo "I''m first too!" normaltarget: normaltarget2 | mefirst2 @echo "normaltarget done" normaltarget2: a b c @echo "normaltarget2 done" helloworld: normaltarget | mefirst @echo "helloworld done" .DEFAULT_GOAL := go go: helloworld @echo "go done" a: @echo a b: @echo b c: @echo c

... imprime lo siguiente:

a b c normaltarget2 done I''m first too! normaltarget done I''m first! helloworld done go done

... en lugar de lo que yo esperaría:

I''m first! I''m first too! a b c normaltarget2 done normaltarget done helloworld done go done

¿Qué estoy haciendo mal?