Search code examples
makefileobsolete

Is it possible to use make to remove obsolete targets


I use make to create thumbnails from image files that will in turn be used to create web pages.

Sometimes I delete a source image and I would like the thumbnail to be removed automatically. The obvious way to do it would be to simply add a rule where the target and prerequisite are swapped but that causes a circular reference and messages like this:

make[2]: Circular image123.jpg <- thumbnails/image123.jpg dependency dropped.

Is there a way to do it or must I use a separate makefile? Actually tried but I can't seem to make that work either. I tried this:

# -*- mode: makefile -*-

images = $(wildcard *.jpg) 
thumbnails = $(wildcard thumbnails/*.jpg) 

.PHONY: all
all : $(images)


# Delete thumbnails if source is not present.
%.jpg: thumbnails/%.jpg
    [ -f "$@" ] || rm "$<"

It didn't do anything except print one line referring to the image that is to be kept.

To summarize: is there a way to use make to remove targets that would not be built if they were missing?


Solution

  • First, let's set up a rule to build the thumbnails:

    images := $(wildcard *.jpg)
    TARGETS := $(addprefix thumbnails/, $(images))
    
    .PHONY: all
    all : $(TARGETS)
    
    thumbnails/%.jpg: %.jpg
        create the thumbnail somehow
    

    Then add some code to find the obsolete thumbnails:

    thumbnails := $(wildcard thumbnails/*.jpg)
    OBSOLETE := $(filter-out $(TARGETS), $(thumbnails))
    

    Then write a rule to remove them:

    .PHONY: purge
    purge:
        rm $(OBSOLETE)
    

    This will cause trouble if there are no obsolete thumbnails, so let's wrap the recipe in a conditional:

    purge:
    ifneq ($(OBSOLETE),)
        rm $(OBSOLETE)
    endif
    

    And finally make purge a prerequisite of all:

    all : $(TARGETS) purge