假设我有以下文件层次结构:
Makefile
dir1/
script.sh
other_files.txt
dir2/
script.sh
other_stuff.dat
dir3/
script.sh
other_data.csv
...其中script.sh
是一个运行而不产生任何可输出输出的脚本(例如echo "Hello world!"
。在我的实例中,每个dir
都是一个R包。)< / p>
我正在尝试创建一个Makefile,它将在每个script.sh
中运行dir
,但前提是目录中的某些内容已更改。到目前为止我尝试的是:
DIRS := dir1 dir2 dir3
RUNFILES := $(DIRS:%=run.%)
.PHONY: all ${DIRS}
all: ${DIRS}
dir2: dir3
% : run.%
run.% : $(wildcard %/*)
$(@D)/script.sh
touch $@
...每次调用script.sh
后,只需触摸新的run.dirX
文件(例如dir/script1.sh; touch run.dir1
)。但这不起作用 - 运行make all
只是说没有目标。
似乎应该有一个干净的方法来做这个没有笨重的解决方案让脚本生成整个makefile ...但我不确定它是什么。有什么想法吗?
答案 0 :(得分:1)
你非常接近。我们可以消除一些不需要的步骤并将runfiles作为主要目标:
DIRS := dir1 dir2 dir3
RUNFILES := $(DIRS:%=run.%)
.PHONY: all
all: $(RUNFILES)
唯一的技巧是,如果我们将wildcard
放在先决条件列表中,Make会在决定构建哪些目标之前扩展它 - 当模式规则仍然只是一个模式规则,并且没有目录时名为“%”的扫描。所以我们使用SECONDEXPANSION
和一个额外的'$'来让Make推迟扩展,直到它选择了词干:
.SECONDEXPANSION:
run.%: $$(wildcard %/*)
@$*/script.sh
@touch $@