Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Makefile: prevent infinite pattern recursion

I thought this is quite simple

%.png: ../figs/%.png
        convert $? -resize '40%' $@

That is, I want to generate an image in this directory from the corresponding image in "../figs/" .

But, the above leads to an infinite chain of dependencies because ../figs/foo.png matches %.png and therefore make tries to check ../figs/../figs/foo.png, which matches %.png and therefore make tries to . . . Eventually, make stops with "File name too long".

I must be missing something. What is a clean solution?

like image 755
Ryo Avatar asked Jul 29 '16 04:07

Ryo


3 Answers

Kill the chain with an empty rule

%.png: ../figs/%.png
    convert $? -resize '40%' $@

../figs/%.png: ;
like image 92
user657267 Avatar answered Nov 15 '22 09:11

user657267


All the answers above are quite interesting. However, I'll like to mention the terminal rule solution:

%.png:: ../figs/%.png
    convert $? -resize '40%' $@

By changing to a double colon ::, we then mark the prerequisites terminal:

One choice is to mark the match-anything rule as terminal by defining it with a double colon. When a rule is terminal, it does not apply unless its prerequisites actually exist. Prerequisites that could be made with other implicit rules are not good enough. In other words, no further chaining is allowed beyond a terminal rule.

Note: only suitable for match-anything rules.

  • What are double-colon rules in a Makefile for?
  • GNU make seems to ignore non-terminal match-anything rules for intermediate files
like image 27
davidhcefx Avatar answered Nov 15 '22 09:11

davidhcefx


user657267's solution is perfect. Another option is to use static pattern rules:

PNGS    := $(patsubst ../figs/%.png,%.png,$(wildcard ../figs/*.png))

all: $(PNGS)

$(PNGS): %.png: ../figs/%.png
    convert $< -resize '40%' $@

clean:
    rm -f $(PNGS)

Computing the list of all targets from the list of all prerequisites has several nice side effects, like the prossibility of adding the all and clean targets, for instance.

like image 28
Renaud Pacalet Avatar answered Nov 15 '22 07:11

Renaud Pacalet