代码之家  ›  专栏  ›  技术社区  ›  Zed

生成通配符子目录目标

  •  17
  • Zed  · 技术社区  · 16 年前

    我想做如下的事情,但显然不起作用。请注意,我还有清洁、测试等目标,所以%可能根本不是一个好主意。

    LIBS=lib/*
    
    all: $(LIBS)
    
    %:
      (cd $@; $(MAKE))
    

    感谢您的帮助!

    3 回复  |  直到 16 年前
        1
  •  34
  •   mrkj    16 年前

    以下内容将与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
    
        2
  •  3
  •   Greg    13 年前

    还有一种方法可以只使用gmake命令列出子目录,而不使用任何shell命令:

    test:
      @echo $(filter %/, $(wildcard lib/*/))
    

    '/' . 要删除它,可以使用替换图案:

    subdirs = $(filter %/, $(wildcard lib/*/))
    test:
      @echo $(subdirs:%/=%)
    

    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
    

    “全部” 'make-rule/%:' '$*' 提取后面的字符串 'make-rule/' 并将其用作配方中的参数。例如,第一个先决条件将如下匹配和扩展:

    make-rule/lib/folder1:
      cd lib/folder1 && $(MAKE)
    
        3
  •  0
  •   klsdjfhsalkjfhl    10 年前

    如果您想调用不同的目标,而不是未知数量的子目录中的所有目标,该怎么办?

    以下Makefile使用宏,因此为多个子目录创建一个转发虚拟目标,以将命令行中的给定目标应用于每个子目录:

    # 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))))
    

    希望这有帮助。在处理并行性时非常有用:make-j12使用具有这些目标的makefile清除树中的所有内容。。。和往常一样:玩make是危险的,不同的元编程层次太接近了,-)