tutorial make create makefile gnu-make

create - makefile linux c



gnu make reloads incluye pero no actualiza los objetivos (1)

Intento crear un Makefile que descargue y procese un archivo para generar objetivos, esta es una versión simplificada:

default: all .PHONY: all clean filelist.d clean: @rm -fv *.date *.d #The actual list comes from a FTP file, but let''s simplify things a bit filelist.d: @echo "Getting updated filelist..." @echo "LIST=$(shell date +/%M)1.date $(shell date +/%M)2.date" > $@ @echo ''all: $$(LIST)'' >> $@ %.date: touch $@ -include filelist.d

Lamentablemente, el objetivo no se actualiza correctamente en la primera ejecución, necesita ejecutarse nuevamente para obtener los archivos. Este es el resultado que obtengo de él:

$ make Getting updated filelist... make: Nothing to be done for `default''. $ make Getting updated filelist... touch 141.date touch 142.date touch 143.date

Estoy usando GNU Make 3.81 cuya documentación indica que vuelve a cargar todo si se cambian los archivos incluidos. ¿Qué está pasando mal?


Usted ha especificado filelist.d como un objetivo .PHONY, por lo que cree que hacer ese objetivo en realidad no actualiza el archivo especificado. Sin embargo, sí lo hace, y los nuevos contenidos se usan en la próxima ejecución. Para la primera ejecución, el archivo que falta no es un error porque include tiene el prefijo con el guión.

Elimina filelist.d de .PHONY. Sin embargo, recuerde que no volverá a regenerarse hasta que lo elimine (ya que no depende de nada).

Por la misma razón, debe incluir "predeterminado" en .PHONY.

Escribí un script de shell en lugar de agrupar todo esto en el archivo MAKE:

#!/bin/bash # Check whether file $1 is less than $2 days old. [ $# -eq 2 ] || { echo "Usage: $0 FILE DAYS" >&2 exit 2 } FILE="$1" DAYS="$2" [ -f "$FILE" ] || exit 1 # doesn''t exist or not a file TODAY=$(date +%s) TARGET=$(($TODAY - ($DAYS * 24 * 60 * 60))) MODIFIED=$(date -r "$FILE" +%s) (($TARGET < $MODIFIED))

Reemplace X con el número máximo de días que pueden transcurrir antes de que filelist.d se descargue nuevamente:

filelist.d: force-make ./less-than-days $@ X || command-to-update .PHONY: force-make force-make:

Ahora filelist.d depende de un objetivo .PHONY, sin ser un falso en sí mismo. Esto significa que filelist.d siempre está desactualizado (los destinos falsos son siempre "nuevos"), pero su receta solo actualiza el archivo periódicamente.

Desafortunadamente, esto requiere que escriba el comando de actualización como un solo comando, y el espacio puede ser un problema si es largo. En ese caso, lo pondría en un script separado también.