数行のbashコマンドを使用してプロジェクトをコンパイルする非常に快適な方法があります。しかし、今はメイクファイルでコンパイルする必要があります。すべてのコマンドが独自のシェルで実行されることを考えると、私の質問はメイクファイルで複数行のbashコマンドを相互に依存して実行する最良の方法は何ですか?たとえば、このように:
for i in `find`
do
all="$all $i"
done
gcc $all
また、誰かが単一行コマンドbash -c 'a=3; echo $a > file'
でさえターミナルで正しく動作するが、メイクファイルの場合は空のファイルを作成する理由を説明できますか?
行の継続にはバックスラッシュを使用できます。ただし、シェルはコマンド全体を1行に連結して受信するため、いくつかの行をセミコロンで終了する必要があることに注意してください。
foo:
for i in `find`; \
do \
all="$$all $$i"; \
done; \
gcc $$all
ただし、find
呼び出しによって返されるリスト全体を取得してgcc
に渡すだけの場合、実際には必ずしも複数行のコマンドは必要ありません。
foo:
gcc `find`
または、よりシェル型の$(command)
アプローチを使用します(ただし、$
はエスケープします):
foo:
gcc $$(find)
質問に示されているように、すべてのサブコマンドは独自のシェルで実行されます。これにより、重要なシェルスクリプトの作成が少し面倒になります-しかし可能です!解決策は、スクリプトをmakeが考慮するものに統合することです単一のサブコマンド(単一行)。
$
に置き換えることにより、スクリプトの$$
の使用を回避します;
を挿入して、スクリプトを単一行として機能するように変換します\
を使用して行末をエスケープします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 ;\
}
もちろん、Makefileを記述する適切な方法は、どのターゲットがどのソースに依存するかを実際に文書化することです。些細なケースでは、提案されたソリューションはfoo
をそれ自身に依存させますが、もちろんmake
は十分に賢く、循環依存関係を削除します。ただし、一時ファイルをディレクトリに追加すると、「魔法のように」依存関係チェーンの一部になります。おそらくスクリプトを使用して、依存関係の明示的なリストを一度だけ作成することをお勧めします。
GNU makeはgcc
を実行して.c
および.h
ファイルのセットから実行可能ファイルを生成する方法を知っているため、実際に必要なのは
foo: $(wildcard *.h) $(wildcard *.c)
コマンドを呼び出すだけで何が問題になりますか?
foo:
echo line1
echo line2
....
2番目の質問では、代わりに$
、つまり$$
を使用して、bash -c '... echo $$a ...'
をエスケープする必要があります。
編集:あなたの例は、このような単一行のスクリプトに書き換えることができます:
gcc $(for i in `find`; do echo $i; done)