「Makefile:6: ***Multiple target mode. Stopped.」で make が停止するのはなぜですか?

「Makefile:6: ***Multiple target mode. Stopped.」で make が停止するのはなぜですか?

ターゲットマークダウンファイルでスライドショーを作成し、表示用にコンパイルしてWebサーバーにアップロードするなどの操作を行います。 makefileにマークダウンを作成したら、手順を設定したいと思います。

PROJNAME = `pwd | grep -oP '(\w|-)+' | tail -n 2 | head -n 1 | tr '[:upper:]' '[:lower:]'`

presentation: slides.pandoc
    pandoc --self-contained --data-dir=$(HOME)/.pandoc --template=slides/revealjs_niels_tmpl.html -V revealjs-url:$(HOME)/.pandoc/revealjs -V theme:solarized slides.pandoc -f markdown -t revealjs -o $(PROJNAME).html

onlinepresent: $(PROJNAME).html
    cp $(PROJNAME).html $(HOME)/Share/index.html

説明する PROJNAMEプロジェクトフォルダ名を見つけて小文字に変換します。これを使用して件名に表示されるメッセージを生成するサンプルフォルダの結果はですws-anno-iipresentationルールはスライドショーをhtmlにコンパイルするために使用されますpandoc。マクロはPROJNAME出力ファイルの名前を定義するために使用されます。マウントされた外部ファイルシステム()にファイルがある場合は、プロジェクト名()を含むファイルを停止onlinepresent場所にコピーする必要がありますmake。存在しない場合は、もちろんルールを最初に適用する必要があります。しかし、コマンドを入力すると、何も起こらずにメッセージが表示されます。ws-anno-ii.htmlSharepresentationmake

プロセスmakeが停止し、Makefile:6: *** multiple target patterns. Stop.行を参照します。onlinepresent: $(PROJNAME).html

なぜこれが起こるのかを説明できる人はいますか?

答え1

make 変数の値はPROJNAME次のとおりです。

`pwd | grep -oP '(\w|-)+' | tail -n 2 | head -n 1 | tr '[:upper:]' '[:lower:]'`

バックティック文字はmakeでは特別ではありません。シェルコマンドでこの変数を使用すると、シェルは逆引用符を表示し、それをコマンドオーバーライドとして解釈します。しかし、makeが解釈する変数を使用すると、バックティックは特別な操作を行いません。onlinepresent: $(PROJNAME).html変数が展開されると、行は次のようになります。

onlinepresent: `pwd | grep -oP '(\w|-)+' | tail -n 2 | head -n 1 | tr '[:upper:]' '[:lower:]'`.html

onlinepresent構文解析を、コロン、、、、、、、、、、、、、、、、、、、、、コロン`pwd、、、\コロンgrep、、、、-oPコロン'(\w|-)+'、、コロン、のままにします。一番右のコロンの左側に複数の単語があるので、「マルチターゲットパターン」です。|tail-n2|head-n1|tr'[upper]''[lower]'`.html

makeが読める場所でシェルコマンドの出力を使用するには、次のように呼び出す必要があります。shell機能。これはGNU make機能であり、他のmake実装には影響しません。

PROJNAME = $(shell pwd | grep -oP '(\w|-)+' | tail -n 2 | head -n 1 | tr '[:upper:]' '[:lower:]'`)

これにより、PROJNAME変数は、小文字に変換された作業ディレクトリの最後から2番目のコンポーネントに設定されます。

現在のディレクトリの使用は脆弱であることに注意してください。つまり、別のディレクトリからターゲットに呼び出すと、makefileが機能しないことを意味します。PROJNAMEターゲットまでのパスから計算する方が強力です。小文字部分でない場合は、make関数を使用して完全に実行できます(問題がある場合)。 (コード分割の目的は、実際にはパス名コンポーネントを抽出することです。)

$(notdir $(patsubst %/,%,$(dir $(patsubst %/,%,$(dir $(abspath $@))))))

ただし、GNU makeには大文字と小文字の変換ツールはありません。とにかくシェルを呼び出す場合は、より簡単にすることができます。

PROJNAME = $(shell set -x; echo '$(abspath $@)' | awk -F/ '{$$0=tolower($$0); print $$(NF-2)}')
onlinepresent: $(PROJNAME).html
        cp $< $$HOME/Share/index.html

$$makefileでの使用に注意してください。これは$シェルコマンドの内容になります。これは、変数が定義されるのではなく使用されるたびに評価されるために機能しますPROJNAME(makeの変数定義は、使用されている場合は使用ごとに拡張され、使用されて=いる場合は読み取り割り当て時に拡張されます:=)。

答え2

走りmake onlinepresentmake目標に向かって歩きonlinepresent、何が必要かを確認する$(PROJNAME).htmlのは一種の間違った...makeの観点から見ると、直接提供される対象がないからです$(PROJNAME).html

私もあなたの割り当てPROJNAMEです可能性結果。

試してみてください

presentation: slides.pandoc
#your pandoc rule
onlinepresent: presentation
#your mv command

これはmake、目標を達成するためにonlinepresent目標が必要であることを示しています。presentationその後、ターゲット表現はmakeにこれが必要であることを知らせるため、新しいルールまたは変更されたslides.pandocルールの場合はそのルールを実行します。slides.pandoc

または

次のようにpresentationターゲット名を変更することもできます。$(PROJNAME).html

$(PROJNAME).html: slides.pandoc
#your pandoc rule
onlinepresent: $(PROJNAME).html
#your mv command

関連情報