106

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.

Rob Bednark
  • 25,981
  • 23
  • 80
  • 125
ocirocir
  • 3,543
  • 2
  • 24
  • 34
  • Many `make` programs have conditions, and also functions to test variables. For GNU Make [please read the documentation](https://www.gnu.org/software/make/manual/make.html). – Some programmer dude Aug 06 '16 at 07:49
  • Depending on what `something` is, you could use `ifeq(,$(TEST))` or if `something` is a shell command perhaps `something || something else`. – tripleee Aug 06 '16 at 08:52
  • 1
    This may be an [XY problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem), please don't use contrived examples. – user657267 Aug 06 '16 at 09:02
  • For those interested, I have found a very good answer in another question [here](https://stackoverflow.com/a/16037145/2430526). – SRG Dec 12 '18 at 17:34

7 Answers7

177

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.

Dummy00001
  • 16,630
  • 5
  • 41
  • 63
  • 3
    But remember that if you pass `TEST=` on the CLI, it overrides `TEST :=` regardless. – Ciro Santilli OurBigBook.com May 07 '18 at 13:26
  • 6
    Rather than use `ifeq($(VAR),)` I would suggest that `ifdef VAR` is cleaner. – UKMonkey May 21 '19 at 08:32
  • 22
    "GNU make is hardly known for elegant solutions. Unless you find trapdoors and minefields to be elegant." Thank you for creating some levity during this painful time. – Mr. S Jun 20 '19 at 20:13
  • 1
    To avoid interpreting whitespace as a non-empty value, you can use the `strip` function, see my answer below. – Danijel Nov 06 '19 at 07:33
  • Also make sure that there are no extra spaces within the parentheses of the ifeq command. These aren't ignored, they are in fact part of the strings to be tested. – JoeAC May 12 '21 at 03:32
  • 1
    "`ifdef VAR` is cleaner" But does not check if variable is defined but empty. `ifeq` does. – Mitar Dec 06 '21 at 09:57
58

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))

Tomi Aarnio
  • 2,446
  • 1
  • 19
  • 14
  • 6
    + 1 + `TGT_DIR := $(or $(TGT_DIR),"the-default-string-value")` for the `$(something else)` to be a hardcoded string to fallback – Yordan Georgiev Oct 28 '21 at 09:29
27

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."

Danijel
  • 8,198
  • 18
  • 69
  • 133
26

Folks, I think there's a simpler solution

KDIR ?= "foo"

From: What is ?= in Makefile

Peter Kahn
  • 12,364
  • 20
  • 77
  • 135
  • 9
    The OP ruled this out in their question: conditional assignment won't trigger if "KDIR" contains the empty string, only if the variable is completely undefined. – ncoghlan Feb 26 '20 at 23:16
  • Yup, I just found this in a blog post. I like this solution best. My use case was `TF?=$(shell which terraform)`. -- EDIT oh I see this was ruled out by OP. – meh Aug 03 '22 at 11:31
10

Just in case anyone stumbled upon putting the condition in the rule itself. below how I did it, thought it might help others.

In Makefile, suppose we have the following rule with check target and we need to check whether var was passed.

check:
    @[ "${var}" ] && echo "all good" || ( echo "var is not set"; exit 1 )

To test this out, run the following commands

$ make check 
  var is not set
  make: *** [check] Error 1  

$ make check var=test
  all good 

So, Now we can pass the variable value or a default value in case it was not passed to a bash script that will be responsible to do the logic. something like the following:

@[ "${var}" ] && ./b.sh ${var} || ./b.sh 'ss'

Here's below what b.sh might look like, though you can add more logic to it.

#!/bin/sh
echo $1
Muhammad Soliman
  • 21,644
  • 6
  • 109
  • 75
  • That's not an answer to the question how to set a Makefile variable if it isn't set. You are testing an environment variable in a shell command executed by make. But from there, you cannot set a variable that applies elsewhere in the Makefile. – Roland Weber Jun 07 '19 at 12:37
  • Thanks @RolandWeber for your comment, It was just a code snippet however I updated my answer with an example that is more addressing current issue in the question. Thanks again hope it helps – Muhammad Soliman Jun 09 '19 at 03:37
7

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.

Victor Sergienko
  • 13,115
  • 3
  • 57
  • 91
1

Setting value to variable in Makefile if value defined

ifdef RELEASE_BRANCH
GIT_TAG=$(shell cat projects/${RELEASE_BRANCH}/GIT_TAG)
else
GIT_TAG=$(shell cat release/DEFAULT_GIT_TAG)
endif