递归制作Q:通用目标*之后*其他目标?

时间:2010-11-02 22:12:29

标签: recursion makefile

我知道递归制作会被视为邪恶等等。无论如何,请耐心等待。

我们使用GNU make管理一个相对较大的项目,该项目大量使用make includes来保持个人make文件的简单性。我想添加一个在其他目标之后执行的目标。更准确地说,问题如下:

我有一个像这样的Makefile:

 PROJ_SRC = a.cpp b.cpp
 PROJ_LIB = ab

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

我想首先在子目录x,y,z中调用make,然后在PWD本身构建lib,然后进入'example'子目段以使用该lib构建示例。

除了示例位之外的所有内容都工作正常,但我无法绕过最后一点的干净解决方案。以下是我尝试过的事情:

 # 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 个答案:

答案 0 :(得分:3)

有一个“制作”目录的高级技巧,因此,例如,您不必在子目录中不必要地运行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 *