рекурсивный make Q .: общая цель * после * других целей? - PullRequest
0 голосов
/ 03 ноября 2010

Я знаю, что рекурсивное создание считается злом, и т. Д. Пожалуйста, потерпите меня в любом случае.

Мы управляем относительно крупным проектом с помощью GNU make, в котором интенсивно используются включения make для упрощения отдельных файлов make.Я хотел бы добавить цель, которая выполняется после другой цели.Точнее говоря, проблема в следующем:

У меня есть такой Makefile:

 PROJ_SRC = a.cpp b.cpp
 PROJ_LIB = ab

 PROJ_SUBDIRS  = x/ y/ z/
 PROJ_EXAMPLES = example/

Я хотел бы сначала вызвать make в подкаталогах x, y, z, а затем собратьlib в самом PWD, и только затем перейдите в подкаталог 'example', чтобы построить примеры с использованием этой библиотеки.

Все, кроме бита примера, работает нормально, но я не могу обернуть голову вокруг чистого решения для этогопоследний битВот что я попробовал:

 # works ok for the target 'all', but nothing else
 all: subdirs ... $(PROJ_OBJ) $(PROJ_LIB_FULL) ... $(PROJ_EXAMPLES)

 # ugly, needs to be adde on all targets, and runs into examples 
 # repeatedly if multiple targets get invoked.
 full_lib:: $(PROJ_LIB_FULL)
 $(PROJ_LIB_FULL):: subdirs
   $(CXX) ...
 ifdef PROJ_EXAMPLES
   $(MAKE) -C $(PROJ_EXAMPLES)
 endif

 # this does not make sense, as it builds the lib even on 'make clean' etc
 $(PROJ_EXAMPLES):: full_lib

Есть идеи, как это обобщить?

PS: извините, если приведенные выше фрагменты не являются на 100% чистым синтаксисом - они просто должныпроиллюстрировать проблему ...

1 Ответ

3 голосов
/ 03 ноября 2010

Существует продвинутый трюк для "создания" каталога, так что, например, вам не придется без необходимости запускать Make в подкаталогах.Но даже без этого вы можете получить довольно чистое решение:

$(PROJ_LIB): $(PROJ_SUBDIRS)
  $(CXX) ...

$(PROJ_EXAMPLES): $(PROJ_LIB)
  $(MAKE) -C $@

.PHONY: clean
clean: TARG=clean
clean: $(PROJ_SUBDIRS)
  $(MAKE) -C $(PROJ_EXAMPLES) $@

.PHONY: $(PROJ_SUBDIRS)
$(PROJ_SUBDIRS):
  $(MAKE) -C $@ $(TARG)

И если вам не нравится этот трюк, позволяющий избежать сборки библиотеки при очистке, вы всегда можете сделать так, чтобы example/ makedir был единственнымчто требует строительства библиотеки.В конце концов, эта зависимость действительно принадлежит example.

РЕДАКТИРОВАТЬ:

Если вы хотите, чтобы example/Makefile обрабатывал зависимость lib,это упрощает вещи.Вы можете аккуратно завернуть рекурсивные цели:

$(PROJ_LIB): $(PROJ_SUBDIRS)
  $(CXX) ...

RECURSIVES = clean distclean veryclean squeakyclean
.PHONY: $(RECURSIVES)

$(RECURSIVES): TARG=$@

ALL_SUBDIRS = $(PROJ_SUBDIRS) $(PROJ_EXAMPLES)

# Maybe you want them all to recurse into the same directories:
$(RECURSIVES): $(ALL_SUBDIRS)

#...or maybe not:
clean veryclean squeakyclean: $(ALL_SUBDIRS)
distclean: $(PROJ_EXAMPLES)

# This part does the recursion:
.PHONY: $(ALL_SUBDIRS)
$(ALL_SUBDIRS)
  $(MAKE) -C $@ $(TARG)

# And you still have to define the top-level rules:

clean:
  rm ...

# Maybe nothing to do at this level for distclean

veryclean:
  rm ... and ...

squeakyclean:
  rm *
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...