質問

私は自分のアプリケーションでは、「LIB」ディレクトリのサブディレクトリの任意の数、自身のMakefileを持つ各が含まれている主なディレクトリを、持っています。

私は、各サブディレクトリのMakefileを呼び出すメインディレクトリ内の単一のMakefileを、持っていると思います。私は手動でサブディレクトリを一覧表示する場合はこれが可能である知っているが、私はそれが自動的に行っているしたいと思います。

私は次のようなものを考えていたが、それは明らかに動作しません。私もきれいで、テストなどの目標を持っているので、%は全くおそらく良いアイデアではないことに注意してください。

LIBS=lib/*

all: $(LIBS)

%:
  (cd $@; $(MAKE))

すべてのヘルプは歓迎です!

役に立ちましたか?

解決

以下は、GNUのmakeで動作します。

LIBS=$(wildcard lib/*)
all: $(LIBS)
.PHONY: force
$(LIBS): force
  cd $@ && pwd
lib内のディレクトリ以外の何かがあるかもしれない場合は、

、あなたは、代わりに使用することができます:

LIBS=$(shell find lib -type d)

複数のターゲットの問題に対処するために、あなたはサブビルドの接頭辞を取り除き、その後、各ディレクトリのための特別な目標を構築することができます:

LIBS=$(wildcard lib/*)
clean_LIBS=$(addprefix clean_,$(LIBS))
all: $(LIBS)
clean: $(clean_LIBS)
.PHONY: force
$(LIBS): force
  echo make -C $@
$(clean_LIBS): force
  echo make -C $(patsubst clean_%,%,$@) clean

他のヒント

gmakeのコマンドのみで任意のシェルコマンドを使わずに、サブディレクトリをリストする方法もあります:

test:
  @echo $(filter %/, $(wildcard lib/*/))

このは'/'末尾にすべてのサブディレクトリの一覧が表示されます。それを削除するには、代替パターンを使用することができます:

subdirs = $(filter %/, $(wildcard lib/*/))
test:
  @echo $(subdirs:%/=%)
存在しないディレクトリに偽の目標 -

次に、実際にあなたが小さなトリックを使用することができ、各サブディレクトリにあるmakefileを実行するルールを作成します。私は、この場合の例は、任意の説明よりも多くを教えてくれますだと思います:

FULL_DIRS =$(filter %/, $(wildcard lib/*/))
LIB_DIRS  =$(FULL_DIRS:%/=%)
DIRS_CMD  =$(foreach subdir, $(LIB_DIRS), make-rule/$(subdir))

make-rule/%:
  cd $* && $(MAKE)

all: DIRS_CMD

基本的には、ターゲット'all'リストの前提条件として、すべてのサブディレクトリ。 LIB_DIRSlib/folder1 lib/folder2が含まれている場合たとえば、その後の拡張は次のようになります:

all: make-rule/lib/folder1 make-rule/lib/folder2

次に、ルール'all'を実行するために、既存のターゲットと、各前提条件を一致させようと、「作ります」。この場合、ターゲットは'make-rule/%:'後の文字列を抽出する'$*'を使用して、レシピ内の引数として使用し'make-rule/'、です。例えば、最初の前提条件は、整合されると、このような展開

make-rule/lib/folder1:
  cd lib/folder1 && $(MAKE)

あなたはサブディレクトリの数が不明ですべてとは異なるターゲットを呼び出すようにしたい場合はどう?

以下のMakefileがので、それらのそれぞれに、コマンドラインから与えられた目標を適用するサブディレクトリの数の転送ダミーターゲットを作成したマクロを使用し

# all direct directories of this dir. uses "-printf" to get rid of the "./"
DIRS=$(shell find . -maxdepth 1 -mindepth 1 -type d -not -name ".*" -printf '%P\n')
# "all" target is there by default, same logic as via the macro
all: $(DIRS)

$(DIRS):
    $(MAKE) -C $@
.PHONY: $(DIRS)

# if explcit targets where given: use them in the macro down below. each target will be delivered to each subdirectory contained in $(DIRS).
EXTRA_TARGETS=$(MAKECMDGOALS)

define RECURSIVE_MAKE_WITH_TARGET
# create new variable, with the name of the target as prefix. it holds all
# subdirectories with the target as suffix
$(1)_DIRS=$$(addprefix $(1)_,$$(DIRS))

# create new target with the variable holding all the subdirectories+suffix as
# prerequisite
$(1): $$($1_DIRS)

# use list to create target to fullfill prerequisite. the rule is to call
# recursive make into the subdir with the target
$$($(1)_DIRS):
      $$(MAKE) -C $$(patsubst $(1)_%,%,$$@) $(1)

# and make all targets .PHONY
.PHONY: $$($(1)_DIRS)
endef

# evaluate the macro for all given list of targets
$(foreach t,$(EXTRA_TARGETS),$(eval $(call RECURSIVE_MAKE_WITH_TARGET,$(t))))

この情報がお役に立てば幸いです。本当に参考になっparalelismを扱うとき:いつものように...これらの目標を持つメークファイルで、ツリー内のすべての-j12クリーンを行います。メイクで遊んでは危険である、プログラミングのさまざまなメタレベルが、一緒に近すぎる - )

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top