0

私は基本的にバグのあるmakefileを調べているので、次のシナリオで混乱しました。

default:
     echo "Build started with $@ at $(ENV_VAR)";\
     ENV_VAR=$(NEW_DIR); \
     cd $(ENV_VAR); \
     $(MAKE);

プログラマーの目的:

基本的に、プログラマーは、環境変数ENV_VARを新しい値(ディレクトリーへのパス)NEW_DIRでオーバーライドしてから、そのディレクトリー内でmakeを再帰的に実行することを意図しています。

このmakefileのバグ:

私が見ているバグは、コーダーが「cd $$(ENV_VAR)の代わりに「cd $(ENV_VAR)」を使用していることです。したがって、このため、実際には「cd」コマンドにオーバーライドされたmake変数を使用せず、代わりに$(MAKE)を実行する前に環境変数の値を使用します。また、パスが存在しないためにcdコマンドが失敗しました。最後に、再帰的なmakeを実行することになります。

私が持っている質問

上記の段落で述べたように、私たちは再帰的な作成のシナリオにあります。興味深いことに、同じターゲットが2回目に呼び出されたときに、$(ENV_VAR)がNEW_DIRのオーバーライドされた値を反映しているのがわかります。これは、私を困惑させます。

サンプル出力:

推定:

NEW_DIR = / new-dir OLD-DIR = / old-dir

出力:

Build started with default at /old-dir
bin/sh /old-dir: no such file (or) directory
Build started with default at /new-dir

これに関する提案をお願いします。

4

1 に答える 1

1

あなたは正しいです、それ$(ENV_VAR)は間違っています。しかし、$$(ENV_VAR)それも正しくありません。

Makeはコマンド内の変数を展開してから、コマンドをシェルに渡します。シェルは独自の展開を行います。それで

default:
     echo "Build started with $@ at $(ENV_VAR)";\
     ENV_VAR=$(NEW_DIR); \
     cd $(ENV_VAR); \
     $(MAKE);

シェルコマンドになります

echo "Build started with $@ at /old_dir";\
ENV_VAR=/new_dir; \
cd /old_dir; \
make

このコマンドはまだ実行されていません。割り当てはまだ行われておらず、もう手遅れです。

提案されたソリューションも機能しません。これ:

default:
     echo "Build started with $@ at $(ENV_VAR)";\
     ENV_VAR=$(NEW_DIR); \
     cd $$(ENV_VAR); \
     $(MAKE);

これになります:

echo "Build started with $@ at /old_dir";\
ENV_VAR=/new_dir; \
cd $(ENV_VAR); \
make

これは良さそうに見えますが、シェル構文ではなく、 Makecd $(ENV_VAR);構文であることに注意してください(少なくともbashではありません)。正しいシェル構文は、であるため、ルールは次のようになります。cd $ENV_VAR

default:
     echo "Build started with $@ at $(ENV_VAR)";\
     ENV_VAR=$(NEW_DIR); \
     cd $$ENV_VAR; \
     $(MAKE);

マニュアルによると、「デフォルトでは、環境またはコマンドラインからの変数のみが再帰呼び出しに渡されます」(ただし、必要に応じてこの動作をオーバーライドできます)。は環境変数であるためENV_VAR、サブメイクに渡され、コマンドシェルで変更すると、サブメイクは変更された値を受け取ります。

最後に、この方法で試してみることをお勧めします。

default:
    echo "Build started with $@ at $(ENV_VAR)";
    Make -C $(NEW_DIR) ENV_VAR=$(NEW_DIR);
于 2012-09-14T11:57:39.523 に答える