すべてのコマンドが独自のシェルで実行されることを考えると、makefileで複数行のbashコマンドを実行するための最良の方法は何ですか?たとえば、次のようになります。
for i in `find`
do
all="$all $i"
done
gcc $all
行の継続には円記号を使用できます。ただし、シェルは1行に連結されたコマンド全体を受け取るため、一部の行をセミコロンで終了する必要があることに注意してください。
foo:
for i in `find`; \
do \
all="$$all $$i"; \
done; \
gcc $$all
ただし、呼び出しによって返されたリスト全体を取得してにfind
渡したい場合gcc
は、実際には必ずしも複数行のコマンドは必要ありません。
foo:
gcc `find`
または、よりシェルの従来のアプローチを使用します(ただし、エスケープ$(command)
に注意してください)。$
foo:
gcc $$(find)
質問に示されているように、すべてのサブコマンドは独自のシェルで実行されます。これにより、重要なシェルスクリプトの記述が少し面倒になりますが、それは可能です。 解決策は、スクリプトを、makeが単一のサブコマンド(単一行)と見なすものに統合することです。
$
で置き換えることにより、スクリプトの使用を回避します$$
;
コマンド間に挿入して、スクリプトを1行として機能するように変換します\
set -e
、サブコマンドの失敗時に中止するmakeのプロビジョニングに一致するように開始します()
たりすることができます。{}
これは、一般的なmakefileコマンドシーケンスではありません。OPに触発された例を次に示します。
mytarget:
{ \
set -e ;\
msg="header:" ;\
for i in $$(seq 1 3) ; do msg="$$msg pre_$${i}_post" ; done ;\
msg="$$msg :footer" ;\
echo msg=$$msg ;\
}
ONESHELLディレクティブを使用すると、同じシェル呼び出しで実行される複数の行レシピを作成できます。
all: foo
SOURCE_FILES = $(shell find . -name '*.c')
.ONESHELL:
foo: ${SOURCE_FILES}
FILES=()
for F in $^; do
FILES+=($${F})
done
gcc "$${FILES[@]}" -o $@
ただし、欠点があります。特殊なプレフィックス文字('@'、'-'、および'+')の解釈が異なります。
https://www.gnu.org/software/make/manual/html_node/One-Shell.html
もちろん、Makefileを作成する適切な方法は、どのターゲットがどのソースに依存しているかを実際に文書化することです。些細なケースでは、提案されたソリューションはfoo
それ自体に依存しますが、もちろん、make
循環依存を削除するのに十分賢いです。ただし、ディレクトリに一時ファイルを追加すると、「魔法のように」依存関係チェーンの一部になります。おそらくスクリプトを介して、依存関係の明示的なリストを一度だけ作成することをお勧めします。
GNU makeは、ファイルgcc
のセットから実行可能ファイルを生成するために実行する方法を知っているので、実際に必要なのは.c
.h
foo: $(wildcard *.h) $(wildcard *.c)
コマンドを呼び出すだけの何が問題になっていますか?
foo:
echo line1
echo line2
....
そして、2番目の質問では、代わりに$
を使用してエスケープする必要があります。$$
bash -c '... echo $$a ...'
編集:あなたの例は次のような1行のスクリプトに書き直すことができます:
gcc $(for i in `find`; do echo $i; done)