Frage

Ich habe eine „lib“ Verzeichnis in meine Anwendungen Hauptverzeichnis, die eine beliebige Anzahl von Unterverzeichnissen enthält, von denen jeder seine eigenen Makefile.

Ich mag ein einziges Makefile im Hauptverzeichnis haben, dass Anrufe bei jedem Makefiles-Unterverzeichnis. Ich weiß, dass dies möglich ist, wenn ich manuell die subdirs Liste, aber ich möchte es automatisch getan haben.

Ich dachte an so etwas wie die folgenden, aber es funktioniert offensichtlich nicht. Beachten Sie, dass ich auch sauber haben, Test usw. Ziele, so% wahrscheinlich keine gute Idee überhaupt.

LIBS=lib/*

all: $(LIBS)

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

Jede Hilfe ist willkommen!

War es hilfreich?

Lösung

Im Folgenden wird mit GNU make arbeiten:

LIBS=$(wildcard lib/*)
all: $(LIBS)
.PHONY: force
$(LIBS): force
  cd $@ && pwd

Wenn es etwas anderes als Verzeichnisse in lib sein könnte, könnte man alternativ verwenden:

LIBS=$(shell find lib -type d)

die mehrere Ziele Problem zu adressieren, können Sie spezielle Ziele bauen für jedes Verzeichnis, dann das Präfix für den Teil build abzustreifen:

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

Andere Tipps

Es gibt auch eine Art und Weise der Auflistung Unterverzeichnisse mit gmake Befehlen nur, ohne Shell-Befehle:

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

Hier werden alle Unterverzeichnisse mit '/' Hinter. Um sie zu entfernen können Sie das Ersatzmuster verwenden:

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

Dann tatsächlich zu schaffen Regeln Makefiles in jedem Unterverzeichnis ausführen Sie einen kleinen Trick anwenden können - ein Pseudoziel in einem nicht vorhandenen Verzeichnis. Ich denke, in diesem Fall ein Beispiel mehr als jede Erklärung sagen wird:

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

Grundsätzlich listet Ziel 'all' alle Unterverzeichnisse als Voraussetzungen. Zum Beispiel, wenn LIB_DIRS lib/folder1 lib/folder2 enthalten dann würde die Expansion wie folgt aussehen:

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

Dann ‚make‘, um Regel 'all' auszuführen, versucht, jede Voraussetzung mit einem bestehenden Ziel anzupassen. In diesem Fall ist das Ziel 'make-rule/%:', die '$*' verwendet die Zeichenfolge nach 'make-rule/' zu extrahieren und verwendet sie als Argument in der Rezeptur. Zum Beispiel würde die erste Voraussetzung wie folgt angepasst und erweitert werden:

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

Was ist, wenn Sie verschiedene Ziele als alle in einer unbekannten Anzahl von Unterverzeichnissen nennen wollen?

Das folgende Makefile verwendet Makros, um ein Weiterleitungs Dummy-Ziel für eine Reihe von Unterverzeichnissen des gegebene Ziel von der Kommandozeile zu jedem von ihnen gelten:

# 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))))

Hope, das hilft. Wirklich hilfreich, wenn sie mit paralelism tun: make -j12 alle sauber in einem Baum mit Makefiles, diese Ziele mit ... Wie immer: spielen mit Make ist gefährlich, verschiedene Meta-Ebenen der Programmierung sind zu dicht beieinander, -)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top