49

How and when do I quote a string in a make file? What is best practice?

Is the following the way to quote?

$(warning  $(shell ls -ld "$(CURDIR)" ) )

I'm familiar with Bash where you usually quote variables to allow for embedded spaces. Do you do such in a makefile?

How should I do assignment statements with a string?

vara := "$(CURDIR)"

varb := $(CURDIR)

varc := /home/me/source

vard := "/home/me/source"

What about the space after the equal?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
historystamp
  • 1,418
  • 4
  • 14
  • 24

1 Answers1

51

You should never quote anything because of make. Make doesn't understand or parse single- or double-quote characters in any way. Every quoting character you write in a makefile will be kept as a literal quote and passed along as-is to the commands that make invokes.

So, if the shell expects and can interpret a quoted string, then you should use quotes. Where the shell doesn't expect or won't correctly interpret a quoted string, you should not use quotes.

In your examples, whether the quotes are acceptable or not depends on how those variables are used. As above, make won't do anything special with quotes, which means that vard (for example) contains the literal string "/home/me/source" (including the quotes).

If you use that value in a way where the shell will handle the quotes for you, then it's fine:

all: ; echo $(vard)

will print /home/me/source (no quotes) because the shell interprets them. But if you use the variable in a make context, for example as a target or a prerequisite:

all: $(vard)
$(vard): ; echo $@

then this is not right, because the target and prerequisite are the literal strings "/home/me/source" (including the quotes).

In general it's best to not use quotes around filenames in variables, and instead add the quotes in the recipe around the make variable. Of course if the variable contains an entire shell script, not just a filename, then you should add appropriate quoting to the script.

MadScientist
  • 92,819
  • 9
  • 109
  • 136
  • ifequ "$(varx)" "a" was the partial source of confusion for me. – historystamp Apr 28 '14 at 21:13
  • 2
    One upshot of this is that _make_ cannot abide spaces in filenames. Space is the list separator and—as MadScientist points out—is not quotable. _make_ usually breaks up such a filename into useless fragments. – bobbogo Apr 30 '14 at 12:52
  • 9
    might not be relevant to the OP's intent, but other users might land here and not understand the distinction between _make variables_ like `$(VARX)` and _shell variables_ like `$${VARZ}` - note the double dollar sign `$$` which make uses to distinguish between them _and so_ in the situation when you want to pass a shell variable to a command as a variable **without expansion** then you might want to use single quotes, EG: passing `$ORIGIN` to the linker, then use `cc -Wl,-rpath='$${ORIGIN}' -shared -fPIC -Wall $(SRC) -o $(DIR)/$(LIB)` with single quotes to keep it from expanding in the shell. – Mark Mikofski Oct 02 '17 at 18:13
  • regarding my comment, see [MadScientists's answer on how to correctly pass `$ORIGIN` to the linker in a make file](https://stackoverflow.com/a/42347206/1020470) in which both single quotes and the double dollar sign are used, but the syntax of [`-Wl,option`](https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html) is slightly different than my example – Mark Mikofski Oct 02 '17 at 18:19