makefile - 在一个规则中制作“make”更改跟踪两个目录
问题描述
我正在使用 GNU Make,但如有必要,我愿意更改为其他内容。
我有两个目录ALPHABETIC
,NUMERIC
内容如下。
./ALPHABETIC:
A.txt B.txt C.txt
./NUMERIC:
1.txt 2.txt 3.txt
和一个程序foo
,它将一个文件ALPHABETIC
和一个文件作为输入NUMERIC
并输出一些东西。
我想创建一个规则,这样:如果一个文件发生c
变化ALPHABETIC
,重新foo
运行. 如果文件更改,请重新运行. 中的每个文件。c
NUMERIC
n
NUMERIC
foo
n
ALPHABETIC
例如:A.txt
变化。那么应该发生的是:
foo A.txt 1.txt
foo A.txt 2.txt
foo A.txt 3.txt
让我们说现在2.txt
变化。那么应该发生的是
foo A.txt 2.txt
foo B.txt 2.txt
foo C.txt 2.txt
我尝试使用模式规则执行此操作,但没有成功。
解决方案
由于 make 旨在管理从文件生成文件的构建系统,我们首先假设生成一个在主目录中foo A.txt 1.txt
命名的文件。A.1.txt
您可以尝试以下方法:
.PHONY: all
.DEFAULT_GOAL := all
ALPHA := $(patsubst ALPHABETIC/%.txt,%,$(wildcard ALPHABETIC/*.txt))
NUM := $(patsubst NUMERIC/%.txt,%,$(wildcard NUMERIC/*.txt))
# $(1): ALPHA
# $(2): NUM
define ALPHANUM_rule
$(1).$(2).txt: ALPHABETIC/$(1).txt NUMERIC/$(2).txt
@echo foo $(1).txt $(2).txt && \
touch $$@
all: $(1).$(2).txt
endef
$(foreach a,$(ALPHA),$(foreach n,$(NUM),$(eval $(call ALPHANUM_rule,$(a),$(n)))))
注意使用echo
andtouch
来模拟你的真实foo
命令的效果。最重要的是要理解foreach-eval-call
结构,包括为什么某些$
符号需要加倍($$
)。有关详细说明,请参阅 GNU make 手册中的eval函数。
演示(host>
是shell提示符):
host> make
foo B.txt 2.txt
foo B.txt 3.txt
foo B.txt 1.txt
foo A.txt 2.txt
foo A.txt 3.txt
foo A.txt 1.txt
foo C.txt 2.txt
foo C.txt 3.txt
foo C.txt 1.txt
host> make
make: Nothing to be done for 'all'.
host> touch NUMERIC/1.txt
host> make
foo B.txt 1.txt
foo A.txt 1.txt
foo C.txt 1.txt
host> make
make: Nothing to be done for 'all'.
host> touch ALPHABETIC/C.txt
host> make
foo C.txt 2.txt
foo C.txt 3.txt
foo C.txt 1.txt
host> make
make: Nothing to be done for 'all'.
但是如果foo A.txt 1.txt
不生成文件怎么办?在这种情况下,最简单的方法就是生成空文件。我们将在单独的目录中创建它们以便于清理:
.PHONY: all
.DEFAULT_GOAL := all
ALPHA := $(patsubst ALPHABETIC/%.txt,%,$(wildcard ALPHABETIC/*.txt))
NUM := $(patsubst NUMERIC/%.txt,%,$(wildcard NUMERIC/*.txt))
TAGSDIR := tags
$(TAGSDIR):
@mkdir -p $@
# $(1): ALPHA
# $(2): NUM
define ALPHANUM_rule
$(TAGSDIR)/$(1).$(2).txt: ALPHABETIC/$(1).txt NUMERIC/$(2).txt | $(TAGSDIR)
@echo foo $(1).txt $(2).txt && \
touch $$@
all: $(TAGSDIR)/$(1).$(2).txt
endef
$(foreach a,$(ALPHA),$(foreach n,$(NUM),$(eval $(call ALPHANUM_rule,$(a),$(n)))))
还有两点需要理解:
- 使用空文件 (
$(TAGSDIR)/A.1.txt...
) 来跟踪已经完成的内容和时间。 - Order-only 先决条件 用于保证在
$(TAGSDIR)
使用之前创建包含空文件的目录,而不会在每次修改其内容时强制重新构建。
推荐阅读
- css - 带有背景重复的 div:无重复;重复
- neo4j - Neo4j中如何使用两个条件进行查询
- java - 如何正确使用 JVM -XX:MaxRAM 选项?
- python - 将python pandas数据框的行名提取为pandas系列
- sed - sed -f 没有针对多行的输入文件运行多个类似的模式匹配命令,包括连接?
- angular - 从数据库angular2 spring中的表中获取信息
- excel - 有什么方法可以缩短 VBA 中的 IsEmpty() 和 Range 语句?
- python - 嗨,我刚开始 AttributeError:'list' 对象没有属性 'get'
- python - 从csv解析树
- javascript - 单击项目时如何自动关闭移动菜单?