【问题标题】:Makefile, iterate over dirs and exclude someMakefile,遍历目录并排除一些
【发布时间】:2021-06-02 09:47:21
【问题描述】:

在顶层(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

【问题讨论】:

  • 如果SUBDIRS是一个变量,试试$(foreach d,$(SUBDIRS),$(patsubst _%,,$(d)))
  • @tripleee 好主意,谢谢。我过于关注外壳部分。我已经修改了我的帖子以显示SUBDIRS 的来源。
  • ALLMAKEFILES = $(shell find . -maxdepth 2 -not -path '*/_*' -type f -name Makefile)find 期间进行过滤并且运行良好。谢谢@tripleee
  • 您的正则表达式匹配以下划线开头的字符串,当然find 的结果都不会。 (^_|/_) 将匹配并在开头或斜线后立即添加下划线。
  • 哦,谢谢!现在我明白为什么 bash 正则表达式不起作用了!

标签: unix makefile


【解决方案1】:

你有两个问题要解决:

  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 option),这将加快您的构建速度。

注意:不建议在 Makefile 中调用 make。首选$(MAKE)。详情请见this section of the manual

【讨论】:

  • 感谢您。我完全支持更多“自制”解决方案!
猜你喜欢
  • 2021-07-29
  • 2015-05-18
  • 1970-01-01
  • 2019-02-07
  • 2013-12-14
  • 2014-07-31
  • 1970-01-01
  • 2011-05-23
相关资源
最近更新 更多