Makefile test if variable is not empty

The name of the picture


Makefile test if variable is not empty



In a makefile I'm trying to



I've created this simplified makefile to demonstrate my problem. Neither make a or make b executes the body of the if, I don't understand why not.


make a


make b


.PHONY: a b

a:
$(eval MY_VAR = $(shell echo whatever))
@echo MY_VAR is $(MY_VAR)
$(info $(MY_VAR))
ifneq ($(strip $(MY_VAR)),)
@echo "should be executed"
endif
@echo done

b:
$(eval MY_VAR = $(shell echo ''))
@echo MY_VAR is $(MY_VAR)
$(info $(MY_VAR))
ifneq ($(strip $(MY_VAR)),)
@echo "should not be executed"
endif
@echo done



I'm using


$ make --version
GNU Make 3.81





There are several problems, and misunderstandings. Your MY_VAR is a make variable, set it without a <tab> to its value, and no need to $(eval ...). MY_VAR:=$(shell echo whatever) is enough. No <tab> before $(info ...) neither, this is make
– Zelnes
2 hours ago


MY_VAR


make


<tab>


$(eval ...)


MY_VAR:=$(shell echo whatever)


<tab>


$(info ...)


make





If you want to do something if not empty, you need to use $(if $(strip $(MY_VAR)),do if,do else) in the recipe line
– Zelnes
2 hours ago


$(if $(strip $(MY_VAR)),do if,do else)





@Zelnes I only want to set MY_VAR when target a or b is run (the real commands are expensive and there are other targets that don't need it), if I remove the tabs I get syntax errors.
– cerberos
2 hours ago




MY_VAR


a


b





Ahh, a different form of if, works! Please make an answer so I can accept.
– cerberos
1 hour ago




2 Answers
2



If you want to dynamically test the content of MY_VAR, you may have to :


MY_VAR


a:
$(eval MY_VAR = $(shell echo ''))
$(if $(strip $(MY_VAR)),echo ok,echo no)



if evaluation will become echo ok if MY_VAR is not empty, otherwise it will become echo no


if


echo ok


MY_VAR


echo no





Specifically, the ifneq conditionals happen at a different point to the inline $(if ) conditionals: in parsing the Makefile, not when executing the rule.
– Toby Speight
49 mins ago


ifneq


$(if )



Note that, due to the time of evaluation, make conditionals (ifeq, ifneq...) cannot be used in recipes the way you tried. Use shell conditionals, instead, as shown below.


ifeq


ifneq



As your MY_VAR variable is used only in recipes, is target-dependent and you want it to be computed only when needed, why don't you use shell variables, instead of make variables?


MY_VAR


$ cat Makefile
.PHONY: a b

a:
MY_VAR=$$(echo whatever) &&
echo $@: MY_VAR is $$MY_VAR &&
if [ -n "$$MY_VAR" ]; then
echo "$@: should be executed";
fi &&
echo $@: done

b:
MY_VAR=$$(echo '') &&
echo $@: MY_VAR is $$MY_VAR &&
if [ -n "$$MY_VAR" ]; then
echo "$@: should no be executed";
fi &&
echo $@: done

$ make a
a: MY_VAR is whatever
a: should be executed
a: done

$ make b
b: MY_VAR is
b: done



In case you absolutely need MY_VAR to be a target-specific make variable, MadScientist has a wonderful trick that you should probably look at. Applied to your case, it should look like:


MY_VAR


$ make --version
GNU Make 4.1
...

$ cat Makefile
a: MY_VAR = $(eval a: MY_VAR := $$(shell echo whatever))$(MY_VAR)
b: MY_VAR = $(eval b: MY_VAR := $$(shell echo ''))$(MY_VAR)

a:
@echo $@: MY_VAR is $(MY_VAR) &&
if [ -n "$(MY_VAR)" ]; then
echo "$@: should be executed";
fi &&
echo $@: done

b:
@echo $@: MY_VAR is $(MY_VAR) &&
if [ -n "$(MY_VAR)" ]; then
echo "$@: should no be executed";
fi &&
echo $@: done

$ make a
a: MY_VAR is whatever
a: should be executed
a: done

$ make b
b: MY_VAR is
b: done

$ make b a
b: MY_VAR is
b: done
a: MY_VAR is whatever
a: should be executed
a: done



It may look extremely strange but it guarantees that MY_VAR is computed if and only if targets a or b are invoked, and only at most once for each. Have a look at MadScientist's post for detailed explanations. Go, it's brilliant.


MY_VAR


a


b






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

Will Oldham

'Series' object is not callable Error / Statsmodels illegal variable name