makefile

makefile clean target over ifdefs blocking makefile execution


Makefile MWE snippet:

ifdef REVISION
$(info "Revision is ${REVISION}")
else
$(error "REVISION missing, can't compile code")
endif

all:
        echo "Hello"

.PHONY: clean
clean:
        rm -r build

I got a compilation requirement, which is REVISION. If not provided by user, the compilation will fail. However, for the clean step, this REVISION is not necessary, but makefile won't let me execute "clean" target, so I end up with:

make clean REVISION=1

instead of just:

make clean

Is it possible to execute targets without the need to satisfy all those ifdefs? The only solution which came on my mind was setting defaults (REVISION for this case), but currently I don't want to have any if possible.

Any suggestions?


Solution

  • If your make is GNU make or another make that defines the MAKECMDGOALS variable, you can test which goals have been passed on the command line and skip the abort when the only goal is clean:

    ifdef REVISION
    $(info "Revision is ${REVISION}")
    else ifneq ($(MAKECMDGOALS),clean)
    $(error "REVISION missing, can't compile code")
    endif
    
    all:
        echo "Hello"
    
    .PHONY: clean
    clean:
        rm -r build
    

    Still with GNU make, if you want to define a list of goals that cannot be made without a revision defined (instead of excluding only clean from the goals that may cause an abort):

    REVISION_NEEDED_FOR := all build exec
    ifdef REVISION
    $(info "Revision is ${REVISION}")
    else ifneq ($(filter $(REVISION_NEEDED_FOR),$(MAKECMDGOALS)),)
    $(error "REVISION missing, can't compile code")
    endif
    
    all:
        echo "Hello"
    
    .PHONY: clean
    clean:
        rm -r build
    

    And finally, if it is simpler to define a list of goals that can be made without a revision defined:

    REVISION_NOT_NEEDED_FOR := clean help
    ifdef REVISION
    $(info "Revision is ${REVISION}")
    else ifneq ($(filter-out $(REVISION_NOT_NEEDED_FOR),$(MAKECMDGOALS)),)
    $(error "REVISION missing, can't compile code")
    endif
    
    all:
        echo "Hello"
    
    .PHONY: clean
    clean:
        rm -r build
    

    Note: of course, a rule can be fired indirectly, even if its target is not itself a goal, but because a goal depends on it. This is something to consider when listing goals to include/exclude.