如何在 Makefile 中转义空格

6
假设我想将位于/home/me/Google Drive/Foobar/的C++项目编译成一个名为Foobar的可执行文件,并且我想使用GNU Make来使这个过程自动化。
下面是我的Makefile内容:
OUTPUT = $(notdir $(CURDIR))

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

问题在于,由于项目路径中存在空格,notdir 命令解释为两个不同的路径,并返回 Google Foobar
我尝试在 $(CURDIR) 周围加上引号($(notdir "$(CURDIR)")),但是出现以下错误:
/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

我不明白问题来自哪里。
另外,我希望得到一个不需要更改路径名称的答案...谢谢 :)

$(notdir \"$(CURDIR)\") 能够正常工作吗? - Michas
不,它返回“Google Foobar”。 - Naïm Favier
可能是Can GNU make handle filenames with spaces?的重复问题。 - user657267
4个回答

6
你可以尝试将 $(CURDIR) 中的 space 替换为 _,然后获取 $(OUTPUT)。如下所示:
null      :=
SPACE     := $(null) $(null)
OUTPUT     = $(notdir $(subst $(SPACE),_,$(CURDIR)))

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

因此,在字符串替换(subst)之后,实际上
$(OUTPUT) will be Foobar

根据问题的标题,这是正确的答案。 - Géza Török

1
问题不在GNU make存储目录方面,而在于shell扩展方面。因此更改为:
 g++ *.cpp -o $(OUTPUT)

to:

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

使用GNU make的变体remake,您可能会更容易地看到这一点。
使用remake,如果您想验证$OUTPUT的值是否有空格,可以运行:
$ 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

现在如果您想查看一个Shell脚本,执行与GNU make相同的操作,请使用write命令:

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

所有上述内容是“make”目标名称。然后查看“/tmp/all.sh”,它只是一个shell脚本,您会发现您在那里遇到了问题,当然可以通过添加引号来修复该问题。

这个是可以工作的... 但它只是在像 (cd dir && '$(MAKE)') 这样的命令中失败。 - devsaw

0

执行:

OUTPUT = $(notdir $(lastword $(CURDIR)))

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

0

看起来这个组合在这种情况下是有效的。

OUTPUT = "$(notdir $(CURDIR))"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接