Makefile that recompiles only if its dependency actually changed

Viewed 3681

Let's imagine that I have a file that is generated based not on some other file in the file system, but some external command whose output may or may not change. Can I express this concept in the makefile and have dependent targets only run if the content actually changed?

To specific, I have a file date.h which has the current date, hour and minute (but not seconds), which is generated by a rule like this:

echo "#define DATE" '"' $$(date '+%D-%H:%M') '"' > date.h

The default 'app' target depends on date.h and the whole Makefile looks like:

app: date.h
    echo "Building app"
    touch app

date.h: FORCE
    echo "#define DATE" '"' $$(date '+%D-%H:%M') '"' > date.h

FORCE:

Now the FORCE target causes date.h to be rebuild every time, which causes app to always be out of date and get rebuilt.

On the other hand, if I don't include the FORCE target, then date.h will only be rebuilt if it doesn't exist (e.g., after a clean or after initially cloning the project), but never again after that.

What I want is for date.h to be out of date only if its contents were actually changed by the echo - that is, when the minute changes, but not otherwise. Is there some way to tell make to only consider date.h changed if its actual bytes changed on disk, rather than going by the timestamp, or another way to achieve this effect?

Echoing the date to a temporary file and then conditionally updating date.h based on comparing their contents crossed my mind, but I'm not sure if it's a reasonable approach.

2 Answers
Related