2

ここに私のメイクファイルの一部があります:

PATH := $(shell pwd)
EDIR := impl
EFFECTS := $(filter-out $(EDIR), $(shell find $(EDIR) -maxdepth 1 -type d))
ALLMAKES := $(patsubst %, $(PATH)/%, $(EFFECTS))


all:
      $(foreach c,$(ALLMAKES),$(MAKE) -C $(c))

したがって、基本的には、「impl」自体を使用せずに、「impl」ディレクトリ内のすべてのディレクトリに対して make を呼び出したいと考えています。make は最後に -C 引数を指定して呼び出されたときの最後のディレクトリを覚えていることを理解しています。そのため、毎回絶対パスを指定します。エコーを作成するのは、私が望むもののようです:

make -C <projectdir>/impl/thing1 make -C <projectdir>/impl/thing2 make -C <projectdir>/impl/thing3

問題は、make がコマンドを実行せず、次のように出力することです。

make: make: Command not found. 

makefile の外で各ディレクトリに対して「make -C <path>」を個別に呼び出すことができますが、foreach 呼び出しでは機能しません。代わりにこれを試しましたが、どちらも機能しません:

$(foreach c,$(ALLMAKES),$(shell make -C $(c)))

何か案は?

4

1 に答える 1

10

makeこれは、後続のmakeコマンドを含む多くの引数を使用して、単一の を呼び出しているためです。make の呼び出しの間にシェル コマンド セパレータを追加する必要があります。このようなものが動作します:

all:
        $(foreach c,$(ALLMAKES),$(MAKE) -C $(c) && ) true

よく見ると、メイクファイルには他にも問題があります。という名前の make 変数を設定しないでください。PATHサブシェルの$PATH変数が上書きされるからです。$(CURDIR)を実行するのではなく、組み込み変数 make を使用できます$(shell pwd)。実際には、ディレクトリにパスのプレフィックスを付ける必要はまったくありません。実行してもシェルの$(MAKE) -C ...作業ディレクトリは変更されず、make だけであり、make が終了すると元に戻されるため、相対パスを使用できます。

また、ループ内でサブ make を呼び出すと、いくつかの問題があります。まず、取得できる並列化の量を減らします。第二に、-kオプションを適切にサポートすることはできません (多くの不愉快な努力なしには)。この問題を処理するより良い方法は、make がすでに多くのターゲットを構築する方法を知っているという事実を利用することです。

all: $(EFFECTS)
$(EFFECTS):
        $(MAKE) -C $@
.PHONY: all $(EFFECTS)

異なるサブディレクトリ間に特定の順序の問題がある場合は、それらも定義できます。

impl/thing2: impl/thing1

これにより、重要な順序を維持しながら、並列化の機会を最大限に確保できます。

for などの代替ルールを追加するにはclean、次のようにします。

CLEAN_EFFECTS := $(addsuffix .clean,$(EFFECTS))
clean: $(CLEAN_EFFECTS)
$(CLEAN_EFFECTS):
        $(MAKE) -C $(basename $@) clean
.PHONY: clean $(CLEAN_EFFECTS)

make impl/thing1たとえば、実行することで単一のサブディレクトリ (およびそのすべての前提条件) を構築することもできるため、これは便利です。または実行してそれらをきれいにしますmake impl/thing1.clean

これらがもっとある場合は、パターン ルールなどを工夫して、すべてのタイプのターゲットに対してこれを繰り返さないようにすることもできます。それはより面倒になります。

于 2013-03-27T16:32:40.280 に答える