How to conditionally set Makefile variable to something if it is empty?

I want to set a variable if it is empty. I tried in this way:

....
TEST := $(something)
...
TEST ?= $(something else)

The first $(something) may return an empty string, however the conditional assignment ?= works only if the previous variable is not set, not if empty.

Any elegant solution to set the variable if empty?


EDIT I found this solution:

....
TEST := $(something)
...
TEST += $(something else)
TEST := $(word 1, $(TEST))

but I think that there will be one more elegant.


Solution 1:

Any elegant solution to set the variable if empty?

GNU make is hardly known for elegant solutions. Unless you find trapdoors and minefields to be elegant. I know only of the two ways to accomplish what you want:

  1. The standard ifeq/endif solution:

    ifeq ($(TEST),)
    TEST := $(something else)
    endif
    
  2. Use the $(if) function:

    TEST := $(if $(TEST),$(TEST),$(something else))
    

    One can try to package that construct into a function too, but that is inadvisable. The function would have the hidden pitfall of occasionally breaking the $(something else) if it contains the , (for which there are only wayward workarounds). (The built-in functions like $(if) are immune to the , bug.)

Elegance test is up to you.

Solution 2:

Here's another alternative that I personally find quite elegant, because it's a one-liner and doesn't need the redundant else-branch:

TEST := $(or $(TEST),$(something else))

Solution 3:

From GNU make, chapter 7.2, Syntax of Conditionals:

"Often you want to test if a variable has a non-empty value. When the value results from complex expansions of variables and functions, expansions you would consider empty may actually contain whitespace characters and thus are not seen as empty. However, you can use the strip function to avoid interpreting whitespace as a non-empty value. For example:

ifeq ($(strip $(foo)),)
text-if-empty
endif

will evaluate text-if-empty even if the expansion of $(foo) contains whitespace characters."

Solution 4:

Folks, I think there's a simpler solution

KDIR ?= "foo"

From: What is ?= in Makefile

Solution 5:

In case you need to distinguish if a variable is undefined or just has an empty value, use $(origin VARNAME) function:

ifeq ($(origin VARNAME),undefined)
VARNAME := "now it's finally defined"
endif

Note that VARNAME is not surrounded by $() - you literally give the name of the variable.