makefile execute another target

Viewed 194906

I have a makefile structured something like this:

all : 
    compile executable

clean :
    rm -f *.o $(EXEC)

I realized that I was consistently running "make clean" followed by "clear" in my terminal before running "make all". I like to have a clean terminal before I try and sift through nasty C++ compilation errors. So I tried to add a 3rd target:

fresh :
    rm -f *.o $(EXEC)
    clear
    make all

This works, however this runs a second instance of make (I believe). Is there a right way to get the same functionality without running a 2nd instance of make?

3 Answers

If you removed the make all line from your "fresh" target:

fresh :
    rm -f *.o $(EXEC)
    clear

You could simply run the command make fresh all, which will execute as make fresh; make all.

Some might consider this as a second instance of make, but it's certainly not a sub-instance of make (a make inside of a make), which is what your attempt seemed to result in.

You already have a sequential solution which could be rewritten as:

fresh:
    $(MAKE) clean
    clear
    $(MAKE) all

This is correct and a very safe approach.

Sequential target execution is possible in GNU make with a proper dependency graph:

fresh: _all
_all: _clear
    Recipe for all
_clear: _clean
    Recipe for clear
_clean:
    Recipe for clean

The above rules define the following dependency graph: fresh <- _all <- _clear <- _clean which guarantees the following recipe execution order: Recipe for clean, Recipe for clear, Recipe for all.

Recipes can be shared with multiple targets using:

target1 target2 target…:
    recipe1

Merging your script with the above concepts results in:

all _all : 
    compile executable
clean _clean :
    rm -f *.o $(EXEC)
clear _clear :
    clear
fresh: _all
_all: _clear
_clear: _clean

With syntactic sugar using chains.mk from https://github.com/pkoper/mk/ you can write:

all all@fresh :
    compile executable
clean clean@fresh :
    rm -f *.o $(EXEC)
clear clear@fresh :
    clear

@fresh = clean clear all
include chains.mk

fresh: @fresh

Or better:

all: compile

@fresh = clean clear compile
include chains.mk

fresh: @fresh

compile compile@fresh:
    compile executable
clear clear@fresh:
    clear
clean clean@fresh:
    rm -f *.o $(EXEC)
Related