Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to escape spaces inside a Makefile

Let's say I want to compile a C++ project located in /home/me/Google Drive/Foobar/ into an executable named Foobar, and I want to use GNU Make in order to make that process automatic.

Here is what my Makefile looks like :

OUTPUT = $(notdir $(CURDIR))

all $(OUTPUT):
    g++ *.cpp -o $(OUTPUT)

The problem is, since there are spaces in the project's path, the notdir command is interpreting two separate paths and returns Google Foobar.

I've tried putting quotes around $(CURDIR) ($(notdir "$(CURDIR)")) but I get the following error :

/bin/sh: -c: line 0: unexpected EOF while looking for matching `"'
/bin/sh: -c: line 1: syntax error: unexpected end of file
Makefile:4: recipe for target 'all' failed
make: *** [all] Error 1

I don't understand where the problem comes from.

Also, I would appreciate an answer that does not involve changing the path name... Thanks :)

like image 204
Naïm Favier Avatar asked Jun 06 '15 21:06

Naïm Favier


2 Answers

You can try replacing space with _ in the $(CURDIR) and then fetch the $(OUTPUT). Like below

null      :=
SPACE     := $(null) $(null)
OUTPUT     = $(notdir $(subst $(SPACE),_,$(CURDIR)))

all $(OUTPUT):
    g++ *.cpp -o $(OUTPUT)

So essentially after string substitution (subst)

$(OUTPUT) will be Foobar
like image 174
Santosh A Avatar answered Oct 11 '22 11:10

Santosh A


The problem is less on the GNU make side in storing the directory than it is on the shell expansion side. So change

 g++ *.cpp -o $(OUTPUT)

to:

 g++ *.cpp -o "$(OUTPUT)"

Using the variant of GNU make called remake you might be able to see this more easily.

With remake, if you wanted to verify that the value of $OUTPUT has a space in it, you could run:

$ remake -X
GNU Make 4.1+dbg0.91
...
-> (/home/me/Google Drive/Makefile:3)
all: 
remake<0> expand OUTPUT
Makefile:1 (origin: makefile) OUTPUT := Google Drive

Now if you wanted to see a shell script that does the same actions that GNU make will run, use the write command:

remake<1> write all
File "/tmp/all.sh" written.

all above is the make target name. Then look at /tmp/all.sh which is just a shell script and you'll see you have the problem there, which of course can be fixed by adding the quotes.

like image 41
rocky Avatar answered Oct 11 '22 11:10

rocky