Search code examples
makefilegnu-make

Makefiles, ifdef and computed variables


I'm trying to make something that I think it's not possibile in make. I have a common target which can have several prerequisite, like postbuild_% in this example

TARGET_NAMES = release.target.1.1 debug.target.1.1 release.target.2.4 debug.target.2.4
BUILD_TARGET := $(addprefix build_,$(TARGET_NAMES))    
.PHONY: $(BUILD_TARGET)
$(BUILD_TARGET): build_%: prebuild_% % postbuild_%

I use the definition of a variable (exported by another makefile which calls the one with the rules) for each target to determine a certain behaviour of the compilation. Since each target name is different (except for the release/debug thing), I use a different variable for each one. For example

.PHONY: %.target.1.1
%.target.1.1:
ifndef NO_target.1.1
    [something specific for %.target.1.1]
else
    @echo nothing to do
endif

now my problem is that even in postbuild_% I have to replicate this thing, but the recipe is always the same for every target, so I'm trying to find a way to use computed variables to recreate the "NO_$*" variable in order not to replicate the whole recipe, like this

POSTBUILD_TARGET := $(addprefix postbuild_,$(TARGET_NAMES))
.PHONY: $(POSTBUILD_TARGET)
$(POSTBUILD_TARGET): postbuild_%:
ifndef $(addprefix NO_,$(subst $(whitespace),.,$(wordlist 2,4,$(subst ., ,$*))))
    [...]
else
    @echo Skipping $@
endif

Something in this is clearly not working: what am I doing wrong?

Thank you for your help :)


Solution

  • Make first parses all makefiles into an internal data structure, then runs the rules. ifeq etc. are evaluated at the first step. Automatic variables are not set until the second step.

    You cannot use make preprocessor statements like ifeq, which are parsed as the makefile is read in, to query automatic variables like $*, which are not set until the recipe is run.

    You'll have to use shell conditionals if you need to test some value per rule, like this:

    $(POSTBUILD_TARGET): postbuild_%:
            if [ -z '$(NO_$(subst $(whitespace),.,$(wordlist 2,4,$(subst ., ,$*))))' ]; then \
                [...]; \
            else \
                echo Skipping $@; \
            fi