首页 > 解决方案 > Makefile,遍历目录并排除一些

问题描述

在顶层(unix,GNU)Makefile中,我想遍历子目录列表并在其中执行任务,但排除其中一些。在这种情况下,排除所有以下划线 (_) 开头的子目录

以下正在迭代但忽略排除正则表达式。它仍然访问目录“_exclude”。

特别是我认为它忽略了“字符串的开头” ^ (或者它从字面上理解)。我尝试过其他正则表达式,它们确实有效。知道如何解决吗?或者,如果您确实知道如何消除脱壳或不使用 GNU makefile 扩展?

SHELL=/bin/bash
EXCLUDE_DIRS_REGEX=^_
# later addition:
ALLMAKEFILES = $(shell find . -maxdepth 2 -type f -name Makefile)
SUBDIRS   = $(filter-out ./,$(dir $(ALLMAKEFILES)))

all:
    for dir in $(SUBDIRS); do \
        if [[ "$$dir" =~ $(EXCLUDE_DIRS_REGEX) ]]; then continue; fi; \
        make -C $$dir all; \
    done

标签: unixmakefile

解决方案


你有两个问题需要解决:

  1. 计算目标目录列表
  2. 在他们每个人中调用 make

对于第一个,make 和 shell 函数或内置函数的混合可能类似于:

REGEX       := ^_
ALLMAKEDIRS := $(patsubst %/,%,$(dir $(wildcard */Makefile)))
SUBDIRS     := $(shell for d in $(ALLMAKEDIRS); \
    do ! [[ "$$d" =~ $(REGEX) ]] && echo "$$d"; done)

我保留了REGEX以防万一您有更复杂的正则表达式,或者您希望它易于修改。但是,当然,如果它是完全正确的^_并且您永远不会更改它,那么以下内容会更简单:

SUBDIRS := $(filter-out _%,$(patsubst %/,%,$(dir $(wildcard */Makefile))))

对于第二个,你的方法不是很老套。更好的方法是每个子目录有一个规则。下面是一个例子:

.PHONY: all $(SUBDIRS)

all: $(SUBDIRS)

$(SUBDIRS):
    $(MAKE) -C $@ all

它有几个优点:

  • 无需在复杂的配方中循环子目录,make 会为您完成,
  • make 可以并行启动多个作业(请参阅-j选项),这将加速您的构建。

注意:make不建议调用 Makefile。更喜欢$(MAKE). 有关详细信息,请参阅手册的此部分


推荐阅读