5

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'

ここで起こっていることは、が2 つのパスとして$(notdir)解釈され、両方の「ファイル部分」を返すことです(つまり、と)。これの奇妙な部分は、適切にエスケープされていることです。どういうわけか、ルール内または内で、バックスラッシュのエスケープが無視されています。/tmp/space test/foospacefooTARGET$(notdir)

ここで何が間違っていますか?

4

3 に答える 3

9

GNU Makeの$(notdir)関数は、スペースで区切られた引数のリストを取ります。\\一部の関数は、でスペースをエスケープすることをサポートしていますが$(notdir)、それらの1つではありません。

これは機能するはずです:

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

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

notdirこれは、呼び出されたの「スペースセーフ」バージョンを定義しますnotdirx。非常に簡単です。s?最初にすべてのスペースを疑問符に変え(ファイル名に含めることができないことを期待して)、?s変換して戻します。その間に、元のnotdir関数を安全に呼び出すことができます。

GNU Makeとファイル名のスペースに関する優れた要約については、GNUMakeがスペースを含むファイル名と一致するを参照してください

于 2009-07-27T18:45:28.407 に答える
0

Unix シェルを使用していると仮定すると、次のようにシェルアウトできます。

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

同様の戦略は、他の関数にも適用できます。単一の引数として扱いたい、空白に感染したテキストを含む変数を引用符で囲んでください。これにより、他の特殊文字 (引用符を除く) からも保護されます。以下は、ワイルドカード グロブの結果のスペースをダブル バックスラッシュでエスケープする例です。

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

Windows も現在、ディレクトリ名に括弧を入れてC:\Program Files (x86)\makeます。

于 2013-05-25T00:02:25.830 に答える
-1

これは暗闇の中でのショットです。

TOP='"/home/chris/src/tests/make/space test"'
于 2009-07-27T18:32:15.937 に答える