24

コロンを含むファイル名で GNU make を正しく動作させる方法はありますか?

私が直面している特定の問題には、たまたまパターン ルールが関係しています。タブ文字の切り取りと貼り付けに依存しない単純化されたバージョンを次に示します。

% make --version
GNU Make 3.81
Copyright (C) 2006  Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.

This program built for x86_64-redhat-linux-gnu
% cat Makefile
COLON := \:
all: ; true
%.bar: ; cp $< $@
x.bar: x.foo
%.foo: ; touch $@
a$(COLON)b.bar: a$(COLON)b.foo
all: x.bar a$(COLON)b.bar
clean: ; rm -f *.foo *.bar
% make clean
rm -f *.foo *.bar
% make
touch x.foo
cp x.foo x.bar
cp  a\:b.bar
cp: missing destination file operand after `a:b.bar'
Try `cp --help' for more information.
make: *** [a\:b.bar] Error 1

$(COLON) をリテラル : に置き換えると、まったく同じ結果が得られます。バックスラッシュがないと、次のようになります。

Makefile:6: *** target pattern contains no `%'.  Stop.
4

6 に答える 6

14

それが可能かどうかは疑問です。Makefilesのコロンに関するこの説明を参照してください。要約すると、GNU makeは、空白またはコロンを含むファイル名でうまく機能したことはありません。メンテナのPaulD.Smithは、エスケープのサポートを追加すると、既存のmakefileが破損する傾向があると述べています。さらに、このようなサポートを追加するには、コードに大幅な変更を加える必要があります。

ある種の厄介な一時ファイルの配置を回避できる可能性があります。

幸運を!

于 2010-01-12T21:35:20.787 に答える
3

次のハックはうまくいきましたが、残念ながら $(shell) に依存しています。

# modify file names immediately
PRE := $(shell rename : @COLON@ *)
# example variables that I need
XDLS = $(wildcard *.xdl)
YYYS = $(patsubst %.xdl,%.yyy,$(XDLS))
# restore file names later
POST = $(shell rename @COLON@ : *)

wrapper: $(YYYS)
    @# restore file names
    $(POST)

$(YYYS):
    @# show file names after $(PRE) renaming but before $(POST) renaming
    @ls

PRE には := が割り当てられているため、関連するシェル コマンドは XDLS 変数が評価される前に実行されます。重要なのは、後で $(POST) を明示的に呼び出してコロンを元の位置に戻すことです。

于 2014-06-29T00:25:13.123 に答える
0

私はこれがうまくいくと確信していませんが、「宛先ファイルがありません」と言う理由は簡単です:

%.bar: ; cp $< $@

その行は、最初の依存関係からターゲットをコピーすることを示しています。a:b.bar には依存関係がないため、cp は失敗します。何をコピーしたいですか?a:b.foo ? その場合、次のものが必要です。

%.bar: %.foo ; cp $< $@
于 2010-01-12T21:27:44.487 に答える
0

@navjotk によって投稿された回答を機能させることができなかったので、ごまかしてこれを行うだけです。

FILENAME:=foo:bar
foo_bar:
    touch $(FILENAME)

run:
    if [ ! -e "$(FILENAME)" ]; then $(MAKE) foo_bar; fi

出力:

$ make run
if [ ! -e "foo:bar" ]; then /Library/Developer/CommandLineTools/usr/bin/make foo_bar; fi
touch foo:bar

$ ls
Makefile foo:bar

私には十分近い。

于 2020-06-18T16:10:24.710 に答える