我知道递归制作会被视为邪恶等等。无论如何,请耐心等待。
我们使用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%干净的语法 - 它们只是为了说明问题......
答案 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 *