有空格的路径上使用make $(DIR)或$(notdir)(Using Make $(dir) o

2019-07-30 22:14发布

我使用的是类似于一个Makefile下面的代码:

empty:=
space:= $(empty) $(empty)
path_escape = $(subst $(space),\$(space),$(1))

TOP=$(call path_escape,$(abspath .))
TARGET=$(TOP)/foo

$(info TOP='$(TOP)')
$(info TARGET='$(TARGET)')

all: $(TARGET)

$(TARGET):
    touch '$(notdir $@)'

.PHONY: $(TARGET)

如果我用这个在没有空格的目录,说space-test ,它工作正常:

$ make
TOP='/tmp/space-test'
TARGET='/tmp/space-test/foo'
touch 'foo'

但是,如果我在空格的目录使用它,说space test ,然后$(notdir)做错误的事情:

TOP='/tmp/space\ test'
TARGET='/tmp/space\ test/foo'
touch 'space foo'

这里发生的事情是, $(notdir)解释/tmp/space test/foo 两个路径,并返回两者 (即的“文件部分” spacefoo )。 这个怪异的一部分是TARGET是正确转义; 不知何故,规则或内内$(notdir)反斜杠逃逸被忽略。

我在做什么错在这里?

Answer 1:

$(notdir)在GNU使函数采用的参数列表,用空格隔开。 有些功能支持逃逸空间与\\ ,但$(notdir)是不是其中之一。

这应该工作:

s? = $(subst $(empty) ,?,$1)
?s = $(subst ?, ,$1)
notdirx = $(call ?s,$(notdir $(call s?,$1)))

$(TARGET):
    touch '$(call notdirx,$@)'

这定义的“空间安全”的版本notdir称为notdirx 。 这是很简单的: s? 首先关闭所有空格问号(希望他们不能出现在文件名),和?s转换回来。 在这两者之间,我们可以安全地调用原始notdir功能。

有关GNU一个很好的总结制作和文件名称空间,请参阅GNU使会见空格的文件名 。



Answer 2:

假设你有一个Unix外壳,你可以掏出:

notdirx = $(shell basename '$1')
dirx = $(shell dirname '$1')

类似的策略也适用于其他的功能。 只要记住周围包含您要视为一个参数的空白感染文字变量引号。 这也将保护您免受其他特殊字符(除引号!)。 下面就以双反斜线为例逃避任何空格通配符水珠的结果:

$(shell ls -1 '*.foo' | sed 's/ /\\\\ /g')

窗户是把括号中的目录名,现在,太: C:\Program Files (x86)\它目前还不清楚我是什么时候使用这意味着什么make



Answer 3:

这仅仅是一个在黑暗中拍摄:

TOP='"/home/chris/src/tests/make/space test"'


文章来源: Using Make $(dir) or $(notdir) on a path with spaces