「make -f」を使って奇妙な動作を自動化

「make -f」を使って奇妙な動作を自動化

私は一連のディレクトリを持っていますが、いくつかは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を呼び出す前に作業ディレクトリを変更していないことです。


概要:この問題を解決するには、次のいずれかを実行できます。

  1. 作業ディレクトリを変更するシェルスクリプトを変更します。

    #!/bin/bash
    
    for f in *; do
            if [[ -d $f && -f $f/makefile ]]; then
                    echo "Making clean in $f..."
                    (cd $f; make clean)
            fi
    done
    
  2. 明示的に空の規則:

    clean: ;
    
  3. clean目標を偽にする:

    .PHONY: clean
    

上海:

Makeには多くの暗黙のルールがあります。これにより、人々はmakefileを書くことなく単純なプロジェクトからmakeを呼び出すことができます。

このデモを試してください。

  1. 空のディレクトリを作成して変更します。
  2. というファイルを作成しますclean.sh
  3. 走るmake clean

出力:

$ make clean
cat clean.sh >clean 
chmod a+x clean

クッ!これが暗黙の製造規則の力です。より暗黙のルールに関するマニュアルの開発より多くの情報を知りたいです。


残りの未解決の質問に答えてみましょう。

最初のmakefileに対して暗黙のルールを呼び出さないのはなぜですか?明示的なルールで暗黙のルールを無視するからですclean

clean2番目のmakefileのルールが暗黙のルールよりも優先されないのはなぜですか?レシピがないからです。レシピのないルールは、暗黙のルールをオーバーライドせずに前提条件を追加します。より複数のルールのマニュアルを作成するより多くの情報を知りたいです。また見てください明示的な空のレシピを使用してルールのマニュアルを作成します。

サブディレクトリでmakefileを呼び出す前に作業ディレクトリを変更しないと、エラーが発生するのはなぜですか?makeは作業ディレクトリを変更しないからです。 Makeは継承された作業ディレクトリで動作します。技術的にはこれは必ずしもバグではありませんが、ほとんどの場合に発生します。サブディレクトリのmakefileがサブディレクトリで動作するようにしますか?または、親ディレクトリで作業するようにしますか?

cleanmakeが2番目の呼び出しで最初のmakefileの明示的な規則を無視するのはなぜですかclean.shこれで、ターゲットファイルがclean存在するためです。このルールにはclean前提条件がないため、ターゲットを再構築する必要はありません。より間違った宛先のマニュアルを作成するこれは問題を正確に説明します。

three/makefile3番目の呼び出しでターゲットを検索するのはなぜですか?makeは、他の操作を実行する前に常にmakefileを再生成しようとするためです。メイクファイルが明示的に要求されたが存在しない-f場合は特にそうです。よりmakefile 書き換えマニュアルの作成より多くの情報を知りたいです。

関連情報