Override target in makefile to add more commands?

Solution 1:

I've seen this done at several shops. The most common approach is to use double-colon rules, assuming you're using something like GNU make. In your common makefile you would have something like this:

clean::
        # standard cleanup, like remove all .o's:
        rm -f *.o

Note that there are two colons following clean, not just one!

In your other makefile you just declare clean again, as a double-colon rule:

clean::
        # custom cleanup, like remove my special generated files:
        rm -f *.h.gen

When you invoke make clean, GNU make will automagically run both of these "branches" of the clean rule:

% make clean
rm -f *.o
rm -f *.h.gen

It's simple to set up and it composes quite neatly I think. Note that specifically because it is a double-colon rule, you don't get the "overriding commands" errors you normally get when you define two rules for the same target. That's sort of the point of double-colon rules.

Solution 2:

You can write your own clean and make it a preq of the common clean.

clean: myclean

myclean:
    rm whatever

Yours will run first. If for some reason you want the common clean to run first then the solution will be more complicated.

EDIT:

Here is the best solution I can see which runs the common rule before the local one:

include Makefile.common

clean:
    $(MAKE) -f Makefile.common $@
    rm whatever additional things

The include directive is necessary because the local makefile relies on the common one for things other than clean. The local clean rule overrides the common clean rule, but invokes the common clean rule before doing the additional work. (This overriding will cause some warnings, which is a nuisance; I don't know a good way to silence them.)

Solution 3:

Use implicit rules:

existing-target: my-extention

my-extention:
    echo running command 1
    echo running command 2

Very simple make tutorial to ramp up.

When using :: you can run into issues since make complains when you mix single colon : and double colon :: rules:

a:
    echo a

a::
    echo aa

will result in:

. . .
*** target file `a' has both : and :: entries.  Stop.