递归式问:一般目标*在其他目标之后吗? [英] recursive make Q.: generic target *after* other targets?

查看:67
本文介绍了递归式问:一般目标*在其他目标之后吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道递归make被认为是邪恶的,等等.无论如何,请忍受我.

I know that recursive make is deemed evil, etc. Please bear with me anyway.

我们使用GNU make管理一个相对较大的项目,该项目大量使用make include来使单个make文件保持简单.我想添加一个在其他目标之后 被执行的目标.更确切地说,问题出在以下方面:

We manage a relatively large project with GNU make, which heavily uses make includes to keep the individual make files simple. I'd like to add a target which gets executed after other targeted. More precisely, the problem is the following:

我有一个这样的Makefile:

I have a Makefile like this:

 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来构建示例.

I would like to first call make in the subdirs x,y,z, then build the lib in PWD itself, and only then go into the 'example' subdir to build the examples using that lib.

一切正常,但示例代码仍然可以正常工作,但是我无法为最后一点围绕一个干净的解决方案.这是我尝试过的事情:

Everything but the example bit is working fine, but I cannot wrap my head around a clean solution for that last bit. Here are the things I tried:

 # 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

关于如何概括这一点的任何想法?

Any idea on how to generalize that?

PS .:很抱歉,如果以上代码段不是100%整洁的语法-它们只是用来说明问题...

PS.: sorry if the above snippets are not 100% clean syntax - they are just supposed to illustrate the problem...

推荐答案

有一个用于创建"目录的高级技巧,例如,您不必在子目录中不必要地运行Make.但是即使没有,您也可以得到一个非常干净的解决方案:

There is an advanced trick for "making" a directory, so that, for instance, you won't have to run Make unnecessarily in the subdirectories. But even without that you can get a pretty clean solution:

$(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.

And if you don't like that trick for avoiding building the library when cleaning, you could always have the example/ makedir be the one that calls for the building of the library. After all, that dependency really belongs to example.


如果您愿意让example/Makefile处理lib依赖项,则可以简化事情.您可以整齐地包装递归目标:

If you're willing to let example/Makefile handle the lib dependency, that simplifies things. You can wrap up the recursive targets pretty neatly:

$(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 *

这篇关于递归式问:一般目标*在其他目标之后吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆