97

I have a makefile, which includes several other makefiles, which in turn all add to a variable like this:

VAR := Something SomethingElse
VAR += SomeOtherThing

(...)

Now I wish to remove SomethingElse from the VAR variable. What do I put in place of (...) to do this?

I am using GNU Make, and a GNU Make specific solution will be fine.

jww
  • 97,681
  • 90
  • 411
  • 885
Bjarke Freund-Hansen
  • 28,728
  • 25
  • 92
  • 135

3 Answers3

133

You could use the filter-out text function if you're using GNU Make.

OTHERVAR := $(filter-out SomethingElse,$(VAR))
Bjarke Freund-Hansen
  • 28,728
  • 25
  • 92
  • 135
Mat
  • 202,337
  • 40
  • 393
  • 406
  • And you are sure I have to use `=` and not `:=` ? – Bjarke Freund-Hansen Sep 14 '11 at 07:49
  • 1
    Are both correct in the example I gave? If I use `=` I get a makefile error saying something about VAR eventually referring itself in an infinite recursion. (`VAR = $(filter-out SomethingElse,$(VAR))`) – Bjarke Freund-Hansen Sep 14 '11 at 08:51
  • That's why I didn't put `VAR =` in my example. If you need to reset `VAR` you probably need simple expansion. – Mat Sep 14 '11 at 09:01
  • 4
    Just to summarize, it of cause depends on the usage. But in my example the correct answer would be: `VAR := $(filter-out SomethingElse,$(VAR))` (With `:=` and not `=`). Thanks. :) – Bjarke Freund-Hansen Sep 14 '11 at 09:27
  • 16
    Note: Also can be used on multiple items. Eg: `VAR := $(filter-out A B C,$(VAR))`. – checksum Jan 22 '14 at 08:47
  • 2
    Note for anyone else coming along. `filter-out` only works on space separated words. If you need to remove something from a string which is not word separated you can use `subst` instead of `filter-out`. I.e: `$(subst -world,,hello-world)` would give the result `hello`. – Jacob Nov 02 '16 at 15:24
10

On top of the correct answer above:

VAR = bla1 bla2 bla3 bla4 bla5

TMPVAR := $(VAR)
VAR = $(filter-out bla3, $(TMPVAR))

all:
    @echo "VAR is: $(VAR)"

Output:
VAR is: bla1 bla2 bla4 bla5

Note that this breaks all "recursivity" when filter-out is executed, but that might not matter in your case.

  • Is this not expected behaviour? Firs you define VAR normally, then you immediately set TMPVAR thus expanding VAR at this point. Then you reset VAR normally to referrer to a filtered out version of TMPVAR. And in the all target your use VAR and thus expand it. I do not see how this breaks recursivity or is in any way problematic behaviour? – Bjarke Freund-Hansen Oct 18 '16 at 07:43
  • 1
    I might have been unclear with what I meant. Imagine having `BLA1 = bla1`, then `VAR = $(BLA1) bla2 bla3 bla4 bla5` instead of the VAR definition above. Executing `BLA1 += bla1111` after the filter-out will have no effect on the value of VAR, since it will have lost its reference to the value of $(BLA1). – Andreas Mikael Bank Oct 19 '16 at 13:52
0

As I also have a similar situation, I want to add a new answer. In my case there were also commas into the variable string and, more, I wanted to remove the comma and the last word :

VAR = "bla1, bla2"

In this case filter out is not working (not even in the previous answers, when there are no quotes)

My solution is to use subst :

VAR = "bla1, bla2"

TTT = , bla2
TMPVAR := $(VAR)
SUBST = $(subst $(TTT),, $(TMPVAR))
FILT = $(filter-out $(TTT), $(TMPVAR))

subst:
    @echo "subst : $(SUBST)"

filter:
    @echo "filter-out : $(FILT)"
sop
  • 3,445
  • 8
  • 41
  • 84