Makefile 制造;制造;在一个规则中更改跟踪两个目录
我正在使用GNU Make,但如果需要,我愿意更改为其他版本 我有两个目录Makefile 制造;制造;在一个规则中更改跟踪两个目录,makefile,gnu-make,Makefile,Gnu Make,我正在使用GNU Make,但如果需要,我愿意更改为其他版本 我有两个目录字母和数字,内容如下 ./ALPHABETIC: A.txt B.txt C.txt ./NUMERIC: 1.txt 2.txt 3.txt 以及一个程序foo,它将字母中的一个文件和数字中的一个文件作为输入,并输出一些东西 我想创建这样一个规则:如果字母中的文件c发生更改,请在c上重新运行foo,并在数字中重新运行每个文件。如果n中的文件NUMERIC发生更改,请在n上重新运行foo,并按字母顺序运行中的每
字母
和数字
,内容如下
./ALPHABETIC:
A.txt B.txt C.txt
./NUMERIC:
1.txt 2.txt 3.txt
以及一个程序foo
,它将字母中的一个文件和数字中的一个文件作为输入,并输出一些东西
我想创建这样一个规则:如果字母中的文件c
发生更改,请在c
上重新运行foo
,并在数字
中重新运行每个文件。如果n
中的文件NUMERIC
发生更改,请在n
上重新运行foo
,并按字母顺序运行中的每个文件
示例: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
和touch
模拟真实foo
命令的效果。要理解的最重要的事情是foreach eval call
构造,包括一些$
符号需要加倍的原因($
)。有关详细说明,请参见中的
演示(host>
是shell提示符):
但是如果fooa.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…
)来跟踪已经完成的工作和时间
$(TAGSDIR)
用于确保包含空文件的目录在使用前创建,而不会在每次修改其内容时强制重新生成
foo A.txt 1.txt
是否生成一个输出文件,其名称将其标识为A
和1
的产品?这将节省一些工作…很好的答案+100
.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)))))