Override target in makefile to add more commands?

前端 未结 6 678
小蘑菇
小蘑菇 2020-12-23 17:16

At work we use a common makefile that other makefiles include (via the include statement) and it has a generic \"clean\" target that kills some common files. I want to add

相关标签:
6条回答
  • 2020-12-23 17:50

    It seems like the common makefile's rule should be called something like common-clean. Then each main makefile would declare their clean rule as

    clean: common-clean
    

    and you're set.

    If that isn't an option, you could take a look at double colon rules, but those introduce a whole other set of issues to consider.

    0 讨论(0)
  • 2020-12-23 17:52

    Adding another possible solution I've seen for posterity... I know the OP was wary about changing the common makefile, but something like this works and involves minimal changes.

    local makefile 1:

    CLEAN=MyExe1 MyExe2
    ....
    include /my/common/makefile
    

    local makefile 2:

    CLEAN=MyExe3 MyExe4
    ....
    include /my/common/makefile
    

    common makefile:

    clean:
         rm -f *.dep *.o *.a $(CLEAN)
    

    Basically the idea is to define some variable (in this case CLEAN) in each local makefile with all the specific items you want to delete. Then the common makefile runs rm -f on all the common file types to delete, plus whatever was specifically flagged for deletion in each local makefile via the CLEAN variable. If there's nothing specific to delete, simply omit the variable declaration or leave it empty (CLEAN=)

    So now if we run make clean for local makefile 1, it executes

    rm -f *.dep *.o *.a MyExe1 MyExe2
    

    And if we run make clean for local makefile 2, it executes

    rm -f *.dep *.o *.a MyExe3 MyExe4
    
    0 讨论(0)
  • 2020-12-23 17:57

    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.
    
    0 讨论(0)
  • 2020-12-23 18:01

    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.

    0 讨论(0)
  • 2020-12-23 18:02

    For ours, we define a variable, EXTRAFILESTOCLEAN, then when the clean rule runs, it has a step to remove anything specified in the EXTRAFILESTOCLEAN variable

    clean:
        rm -f *.o
    ifdef $(EXTRAFILESTOCLEAN)
        rm -f $(EXTRAFILESTOCLEAN)
    endif
    

    That can cause unexpected problems if you set that variable to weird values, but you could guard against those by adding prefixes or other tests.

    0 讨论(0)
  • 2020-12-23 18:14

    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.)

    0 讨论(0)
提交回复
热议问题