私は一連のディレクトリを持っていますが、いくつかはmakefileを含み、いくつかはターゲットを持っていますclean
。親ディレクトリには単純なスクリプトがあります。
#!/bin/bash
for f in *; do
if [[ -d $f && -f $f/makefile ]]; then
echo "Making clean in $f..."
make -f $f/makefile clean
fi
done
これは、(定義された)「クリーン」ターゲットを持たないmakefileを使用してディレクトリにアクセスするときに奇妙なことをします。たとえば、2つのディレクトリがone
与えられた場合は、two
次のようになります。
/メイクファイル
clean:
-rm *.x
2個/メイクファイル
clean:
2番目のケースでは、「clean」がディレクティブなしで実行されるため、「make clean」を実行すると、次のような結果がtwo
表示されます。
make: Nothing to be done for `clean'.
「クリーン」がない場合と比較:
make: *** No rule to make target `clean'. Stop.
しかし、私が説明する問題の場合、ターゲットが存在するが定義されていない、または存在しない場合、結果は同じです。clean.sh
親ディレクトリで実行。
Making clean in one...
rm *.x
rm: cannot remove `*.x': No such file or directory
make: [clean] Error 1 (ignored)
だからone
きれいにする必要はありません。あまりありません。予想されることです。しかし:
Making clean in two...
cat clean.sh >clean
chmod a+x clean
なぜcat clean.sh>clean
待って?上記のように最小限の例を作成しました。周囲に他のファイルやディレクトリはありません(clean.sh、ディレクトリ1と2、非常に小さなmakefileしかありません)。しかし、clean.shを実行した後はmake
コピーされ、clean.sh > clean
実行可能になりました。 clean.shを再実行すると:
Making clean in one...
make: `clean' is up to date.
Making clean in two...
make: `clean' is up to date.
Press any key to continue...
これ以上のことは、指定されたmakefileをまったく使用しないからです。 「最新」ミステリーターゲットを使用します。
私は関連があることがわかりました:次のようにclean.shからテスト句を削除する場合:
# if [[ -d $f && -f $f/makefile ]]; then
if [[ -d $f ]]; then
makefileなしでディレクトリを作成すると、three
出力の一部に次のものが含まれます。
Making clean in three...
make: three/makefile: No such file or directory
make: *** No rule to make target `three/makefile'. Stop.
私が知っている限り、make
そのようなファイルやディレクトリはありません。マニュアルページはとても簡単に見えます。
-f ファイル、 --file=ファイル、 --makefile=ファイル
Use file as a makefile.
答え1
この動作はバグではありません。これは特徴です。正確な機能と可能なユーザーエラーです。
問題の機能はMakeの暗黙のルールの1つです。あなたの場合は、ファイル「ビルディング」の暗黙のルールです*.sh
。ユーザーエラー、間違いは、サブディレクトリからmakefileを呼び出す前に作業ディレクトリを変更していないことです。
概要:この問題を解決するには、次のいずれかを実行できます。
作業ディレクトリを変更するシェルスクリプトを変更します。
#!/bin/bash for f in *; do if [[ -d $f && -f $f/makefile ]]; then echo "Making clean in $f..." (cd $f; make clean) fi done
明示的に空の規則:
clean: ;
clean
目標を偽にする:.PHONY: clean
上海:
Makeには多くの暗黙のルールがあります。これにより、人々はmakefileを書くことなく単純なプロジェクトからmakeを呼び出すことができます。
このデモを試してください。
- 空のディレクトリを作成して変更します。
- というファイルを作成します
clean.sh
。 - 走る
make clean
出力:
$ make clean
cat clean.sh >clean
chmod a+x clean
クッ!これが暗黙の製造規則の力です。より暗黙のルールに関するマニュアルの開発より多くの情報を知りたいです。
残りの未解決の質問に答えてみましょう。
最初のmakefileに対して暗黙のルールを呼び出さないのはなぜですか?明示的なルールで暗黙のルールを無視するからですclean
。
clean
2番目のmakefileのルールが暗黙のルールよりも優先されないのはなぜですか?レシピがないからです。レシピのないルールは、暗黙のルールをオーバーライドせずに前提条件を追加します。より複数のルールのマニュアルを作成するより多くの情報を知りたいです。また見てください明示的な空のレシピを使用してルールのマニュアルを作成します。。
サブディレクトリでmakefileを呼び出す前に作業ディレクトリを変更しないと、エラーが発生するのはなぜですか?makeは作業ディレクトリを変更しないからです。 Makeは継承された作業ディレクトリで動作します。技術的にはこれは必ずしもバグではありませんが、ほとんどの場合に発生します。サブディレクトリのmakefileがサブディレクトリで動作するようにしますか?または、親ディレクトリで作業するようにしますか?
clean
makeが2番目の呼び出しで最初のmakefileの明示的な規則を無視するのはなぜですかclean.sh
?これで、ターゲットファイルがclean
存在するためです。このルールにはclean
前提条件がないため、ターゲットを再構築する必要はありません。より間違った宛先のマニュアルを作成するこれは問題を正確に説明します。
three/makefile
3番目の呼び出しでターゲットを検索するのはなぜですか?makeは、他の操作を実行する前に常にmakefileを再生成しようとするためです。メイクファイルが明示的に要求されたが存在しない-f
場合は特にそうです。よりmakefile 書き換えマニュアルの作成より多くの情報を知りたいです。