GNU Make and wildcards – missing files

gnu-makemakefile

I have a Makefile with the following type of rule:

%.html:
    ./generate-images.py > $@
    make $(patsubst %.png,%.gif,$(wildcard *.png))

The generate-images script writes not only the HTML file (to stdout) but several .png files to the current directory. The goal here is to convert them to .gif. (not really, but this is an example)

This works if I invoke it directly. The problem is: If I invoke it from another rule where foo.html is a dependency, the wildcard statement fails to find any files. In other words, it just called make with no arguments, which is not what I want here.

What's the deal with the wildcard? Or, is there a better way to do this?

Best Answer

While your problem may be something different, I clearly see one.

The whole text of all commands within the rule is simultaneously processed so that make's functions and variables get expanded. Assume you have no .png files in the directory, and you invoke make so it should regenerate them: a.png and b.png. Then, after you invoke make, the text of the rule would effectively look like this:

file.html:
    ./generate-images.py > file.html
    make 

because at the moment of reading the makefile there were no .png files! After the first line is executed, the files will appear, but the next line was already generated to be just "make".

And only when you invoke your makefile for the second time, will it expand to

file.html:
    ./generate-images.py > file.html
    make a.gif b.gif

This is not what you want. So I suggest doing it in The Right Way.

# If you have batch conversion program, this may be helpful
images.stamp: *.png
     convert_all_images $?
     touch images.stamp

# OR, if you want convert one-by-one with means of make
images.stamp: $(wildcard *.png)
    touch images.stamp

%.gif: %.png
    convert_one --from=$^ --to=$@

# HTML would look like
%.html:
     ./generate-images.py > $@
     make images.stamp

So when you invoke make all, it generates htmls and converts newly generated images. Note that it will only convert the images that are updated, which is what you want.


Thanks to Beta for pointing out the mess with gif/png extensions.

Related Topic