Cómo forzar a Make a reiniciar y recargar los makefiles generados?
La tarea a realizar es la siguiente: una herramienta externa llamada en una receta produce un archivo makefile que debe ser incluido inmediatamente por make. Luego, otra regla, utilizando los datos incluidos, genera más archivos de inclusión. Make debe reiniciar nuevamente y solo entonces procesar las reglas adicionales. Considere el siguiente ejemplo:
$(info ------- Reinicio $(MAKE_RESTARTS))
all:
include a
include b
a: p
touch a
b: a
touch b
Funciona de la siguiente manera:
touch p
make
------- Reinicio
touch a
touch b
------- Reinicio 1
make: No hay nada por hacer para 'all'.
Mi problema es que la regla b necesita los datos incluidos de a, pero b se ejecuta ANTES de incluir la versión actualizada de a. Make debe reiniciarse antes de ejecutar b. ¿Cómo se puede lograr esto? Me gustaría ver lo siguiente:
touch p
make
------- Reinicio
touch a
------- Reinicio 1
touch b
------- Reinicio 2
make: No hay nada por hacer para 'all'.
Es fácil detectar si a fue incluido o no, y la regla para b se puede ocultar cuando a no está incluido. Esto funciona para una compilación limpia, pero no cuando a ya existe en el disco desde una compilación anterior y se activa la regla porque p se actualizó. Solo make sabe si la regla a:p está actualizada, no es posible verificar eso con expresiones condicionales.
¿Hay alguna solución para esto?
Actualización: basado en el consejo de @MadScientist, lo hice funcionar de esta manera:
$(info ------- Reinicio $(MAKE_RESTARTS))
all:
include b
include a
a: p
@echo regla A
touch a
$(eval upd=1)
b: a
@echo regla B
$(if $(upd),@echo b omitido,touch b)
Y la salida es la siguiente:
touch p
make
------- Reinicio
regla A
touch a
regla B
b omitido
------- Reinicio 1
regla B
touch b
------- Reinicio 2
¡Perfecto! Gracias chicos, Feliz Navidad a todos.
davy.ai
Para lograr el comportamiento deseado, las reglas en el archivo makefile deben ser reorganizadas. Las declaraciones
include
para el makefile generado deben venir después de la reglaall
, y se debe añadir una nueva regla para regenerar el makefile incluido. De esta manera, el makefile generado será incluido con el contenido actualizado, permitiendo que la reglab
use los datos de la reglaa
. Aquí tienes un ejemplo:En este ejemplo, la regla
all
depende deb
, que a su vez depende degenerated_makefile
ya
. Sia
aún no está incluido, será creado por la reglaa : p
. La reglagenerated_makefile
está marcada como.PHONY
, lo que significa que siempre se considerará desactualizada y se ejecutará cada vez que se ejecuteb
. Esto asegurará que el makefile incluido esté actualizado antes de ejecutar las reglas que dependen de él.Para regenerar la herramienta externa que genera el makefile, ejecuta
make regenerate_makefile
. Esto actualizará el makefile, y la próxima invocación demake
utilizará el nuevo makefile con reglas actualizadas.