2009-07-27 11 views
5

とパスに$(DIR)または$(notdirを)作るの使用:私はスペースなしのディレクトリにこれを使用する場合は私は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 [email protected])' 

.PHONY: $(TARGET) 

を、 space-testを言う、それが正常に動作します:

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

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

をしかし、私は、スペースを含むディレクトリにそれを使用space testを言うなら、$(notdir)は間違ったことをして

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

私はここで間違っていますか?

答えて

9

$(notdir)機能GNUでは、スペースで区切って、引数のリストを取ることを確認します。機能によっては、エスケープスペースを\\でサポートしていますが、$(notdir)はその1つではありません。

これは動作するはずです:

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

$(TARGET): 
    touch '$(call notdirx,[email protected])' 

これはnotdirxと呼ばれるnotdirの "スペース・安全" のバージョンを定義します。それは非常に単純です:s?は最初にすべてのスペースを疑問符に変えます(ファイル名に含めることはできないことを望みます)。?sは元に戻ります。その間に、元のnotdir関数を安全に呼び出すことができます。

ファイル名のGNU Makeとスペースに関する優れた要約については、GNU Make meets file names with spaces in themを参照してください。

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

同様の戦略は、他の関数に適用できます:あなたはあなたが支払うことができ、Unixのシェルを持っていると仮定すると

+1

ありがとう、ヴィル。このハック(またはそう思われる)を除いて、入力を$(notdir)にエスケープする方法がないことはかなりばかげている。 –

+1

うん。 GNU Makeは実際に、言語と標準関数のバージョン2をオプションで有効にすることができます(後方互換性はありません)。あるいは、実際のプログラミング言語を使ってSConsや何かを使うだけの方がいいかもしれません。 –

0

これは、暗闇の中でだけでショットです:

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

ゲイリー、私はあなたを憎んでいない、私は愛に満ちている。個人的に投票権を奪取しないでください。彼らは、答えが正しいか、そして/または有用であるかどうかを伝えるだけです。この場合、いいえ、これは機能しません。 –

+6

私たちは**あなた**をdownvotingしていません、私たちは**答え** downvotingしています。それについて悪い気にしないでください。 – JesperE

0

。単一の引数として扱いたい空白に感染したテキストを含む変数の前後の引用符を覚えておいてください。これはあなたを他の特殊文字から保護します(引用符を除いて!)。あまりにも、

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

Windowsは今ディレクトリ名に括弧を入れている:ここでは、二重のバックスラッシュの例では、ワイルドカードグロブの結果には、スペースをエスケープだC:\Program Files (x86)\それは、このときの意味が何であるか、まだ私には明らかではありませんmakeを使用してください。

関連する問題