在外壳输出上过滤掉

时间:2020-08-04 13:38:56

标签: makefile gnu-make

我的src目录中有四个文件夹:dir1,dir2,dir3,dir4。

PARSE_MODULES = $$(MODULES=$$(ls -l $1 | grep '^d' | awk '{print $$9}'); echo $$MODULES);
MODULES:=$(call PARSE_MODULES,src)
all:
    @echo $(MODULES)

因此,这小段代码输出

dir1 dir2 dir3 dir4

现在,我在all规则之前添加以下两行:

X:=dir1 dir3
MODULES:=$(filter-out $(X),$(MODULES))

输出保持不变,即filter-out无法正常工作。但是,如果我手动定义MODULES,则会得到预期的输出:

MODULES:=dir1 dir2 dir3 dir4
X:=dir1 dir3
MODULES:=$(filter-out $(X),$(MODULES))

输出: dir2 dir4

为什么无法在过滤输出中处理awk的输出?有什么办法吗?

3 个答案:

答案 0 :(得分:4)

您的问题是,您已经通过使用PARSE_MODULES推迟了$$内容的扩展,因此它是由配方中的外壳而不是由make运行。

此:

PARSE_MODULES = $$(MODULES=$$(ls -l $1 | grep '^d' | awk '{print $$9}'); echo $$MODULES);
MODULES:=$(call PARSE_MODULES,src)

留下包含以下文本的MODULES变量:

$(MODULES=$(ls -l src | grep '^d' | awk '{print $9}'); echo $MODULES);

然后,当您在食谱中使用$(MODULES)时,它会像这样展开:

all:
        @echo $(MODULES=$(ls -l src | grep '^d' | awk '{print $9}'); echo $MODULES);

然后外壳程序将在$(...)内部运行命令并回显结果。

当您尝试从make变量dir1的值中滤除MODULES等名称时,什么都不会发生,因为make变量MODULES包含shell脚本本身,如文本,它不包含执行shell脚本的结果。

我不确定为什么您要尝试以如此令人费解的方式来做事情,并且要进行大量的转义并使用难以理解的shell脚本。也许是因为您的整个环境需要一些复杂的原因,但是您可以 FAR 仅使用一些基本的make函数就可以更轻松地实现上述示例:

PARSE_MODULES = $(sort $(notdir $(patsubst %/.,%,$(wildcard $1/*/.))))

MODULES := $(call PARSE_MODULES,src)

现在,PARSE_MODULES通过make而不是通过配方扩展,并且filter-out等可以在其上正常工作。另外,使用grep和awk进行shell操作要简单得多。

答案 1 :(得分:1)

据我了解,执行$(MODULES=$(ls -l src | grep '^d' | awk '{print $9}'); echo $MODULES)的配方时,shell会评估shell列表all。为时已晚。试试这个,也许:

PARSE_MODULES = $(shell ls -l $1 | grep '^d' | awk '{print $$9}')
MODULES       := $(call PARSE_MODULES,src)

X             := dir1 dir3
MODULES       := $(filter-out $(X),$(MODULES))

all:
    @echo $(MODULES)

答案 2 :(得分:1)

OP版本的次要简化:

# possibly: find -maxdepth 1
PARSE_MODULES = $(shell find $1 -type d -printf "%P\n")
SKIP := dir1 dir3

MODS := $(call PARSE_MODULES,src)
FLTR := $(filter-out $(SKIP), $(MODS))

all:
    @echo MODS: $(MODS)
    @echo SKIP: $(SKIP)
    @echo FLTR: $(FLTR)

输出:

MODS: dir1 dir2 dir3 dir4
SKIP: dir1 dir3
FLTR: dir2 dir4