我的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
的输出?有什么办法吗?
答案 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