1

I want to perform a string substitution in my Makefile. I can easily do this with a string literal like so:

foo:
    echo $(subst /,-,"hello/world")

Which yields the expected:

hello-world

But when I switch to using a variable, I can't seem to get the substitution to stick:

foo:
    x="hello/world" ; \
    echo $(subst /,-,$$x)

Instead of replacing the slash with a dash, I still get the original string printed back. Can someone explain what is going on here? Does the variable need to be explicitly converted to a string literal or something?

UPDATE:

The fix based on MadScientist's answer--this will allow me to reference the modified string as a variable.

foo:
    x="hello/world" ; \
    y=`echo $$x | tr / -` ; \
    echo $$y

But instead of echo $$y this could be something more useful.

Community
  • 1
  • 1
jCuga
  • 1,523
  • 3
  • 16
  • 28
  • I don't know exactly what you mean by "_in a subsequent command_", but if you mean in a different recipe this won't work. Each logical line of each recipe is run in a separate shell instance. Every time the shell exits, all the variables it had set (even exported ones) are lost: there's no way for a shell to modify the environment or variables of the process that invoked it (in this case make). – MadScientist Mar 02 '15 at 19:19
  • I simply meant if you wanted to use the resulting substitution by setting it to a variable and using it as i have in my update where I echo the new variable. Not in another make block, etc – jCuga Mar 02 '15 at 19:30
  • In this simple case you could just write `x=$(subst /,-,"hello/world") ; echo $$x` but presumably `x` is really being set to the output of some other command, or something, not a static string. – MadScientist Mar 02 '15 at 19:56

2 Answers2

4

You can't combine make functions with shell variables... all make functions are expanded first, then the resulting script is passed to the shell to be run. When the shell gets the script there are no more make functions in it (and if there were, the shell wouldn't know what to do with them!)

Your subst is running on the literal string $x, which has no / so nothing to replace and results in $x, which the shell expands to the string hello/world.

If you have to work on a shell variable value you must use shell commands such as sed or tr, not make's subst function:

foo:
        x="hello/world" ; \
        echo $$x | tr / -
MadScientist
  • 92,819
  • 9
  • 109
  • 136
  • Thanks for clearing that up for me! I'm going through a bit of a crash course on Make/bash. – jCuga Mar 02 '15 at 19:07
0

You could define x as a make variable:

Makefile:

x = foo bar baz

t:
    @echo $(subst bar,qux,$(x))

Output:

make                                                                                                                                                                                                                                                     
foo qux baz

Version:

make --version                                                                                                                                                                                                                                           
GNU Make 3.81   
Nicolas Lykke Iversen
  • 3,660
  • 1
  • 11
  • 9