Grigory Rechistov
Grigory Rechistov

Reputation: 2234

What will happen if execution of a Make recipe does not change the target file?

We have a Makefile with a recipe that invokes a script to generate a C header that is then included into many other source files:

gen-header.h: $(INPUT)
    script.py $(INPUT) -o gen-header.h

# GMake and GCC rules to produce and include .d files for .c files 
# to track header/source dependencies follow

Recently, an optimization was added to script.py so that it avoids overwriting the output file if it exists and its contents would not change (e.g. if only non-functional comments in $(INPUT) have been updated). Neither access nor creation times of the output gen-header.h would be updated in such case.

The intended goal of the optimization is of course to avoid recompilation of all files depending on gen-header.h whenever changes in $(INPUT) are not propagating to the header (there are other generation passes which use different parts of $(INPUT) to produce different source files unrelated to gen-header.h)

The question is: would such situation confuse Make, or is it an acceptable behavior for a recipe?

Upvotes: 0

Views: 61

Answers (2)

Norman Gray
Norman Gray

Reputation: 12514

It wouldn't confuse make, as such, and would be harmless in this particular case, since the only result would be the action script.py $(INPUT) -o gen-header.h being re-run redundantly each time Make is run.

However, you'd want to avoid this in general.

A rule like

target: source
    action

is, in a sense, a ‘promise’ to Make that running the action will result in target being newer than source. I would experience zero surprise to discover that there were circumstances (possibly involving side-effects of the action?) where this did cause a problem.

Fortunately, this is easy to avoid. In this case I'd write

# Note: `script.py` doesn't rewrite `gen-header.h` if it wouldn't change
gen-header.h: $(INPUT)
    script.py $(INPUT) -o gen-header.h && touch $@

...if only to remind myself that this happens, when debugging the Makefile in future. That forces the target file $@ to be newer, and so keeps the implicit promise to Make.

Upvotes: 0

John Bollinger
John Bollinger

Reputation: 181199

The question is: would such situation confuse Make, or is it an acceptable behavior for a recipe?

Would it confuse make? No. make does not inherently fail if the recipe for a target does not build that target, or does not build it on every run. It might or might not cause a problem for your build, depending on that and other details of your makefile, but the case you describe sounds benign.

Upvotes: 0

Related Questions