سؤال

ولدي "ليب" دليل في بلدي تطبيقات الدليل الرئيسي الذي يحتوي على عدد التعسفي من الدلائل، ولكل منها الخاصة ماكيفيلي لها.

وأود أن يكون ماكيفيلي واحد في الدليل الرئيسي، الذي يدعو ماكيفيلي كل دليل فرعي ل. أعرف أن هذا ممكن إذا أنا يدويا سرد دليل فرعي، ولكن أود أن عليها القيام به تلقائيا.

وكنت أفكر في شيء من هذا القبيل ما يلي، ولكنه من الواضح أنه لا عمل. علما بأن لدي أيضا نظيفة، واختبار، الخ الأهداف، لذلك٪ وربما ليست فكرة جيدة على الإطلاق.

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:%/=%)

وبعد ذلك لخلق الواقع قواعد تنفيذ makefiles في كل دليل فرعي يمكنك استخدام خدعة صغيرة - هدف زائفة في دليل غير موجود. أعتقد أنه في هذه الحالة على سبيل المثال سوف اقول أكثر من أي تفسير:

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_DIRS الواردة lib/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)

وماذا لو كنت تريد الاتصال أهداف مختلفة من كل ذلك في عدد غير معروف من الدلائل؟

ووماكيفيلي التالية يستخدم وحدات الماكرو خلق ذلك الشحن دمية المستهدفة لعدد من الدلائل إلى تطبيق هدف معين من سطر الأوامر لكل واحد منهم:

# 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 تنظيف جميع في شجرة مع makefiles وجود هذه الأهداف ... كما هو الحال دائما: اللعب مع جعل أمر خطير، مختلفة الفوقية مستويات البرمجة هي قريبة جدا معا، -)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top