我想使用 make
并创建一个静态模式规则,目标位于 output
目录中,先决条件文件位于前面的目录中,并且它有递归地工作。
我这里有一个最小的例子:
.
├── anotherdir
│ ├── output
│ │ ├── source3.md
│ │ └── source4.md
│ ├── source3.json
│ └── source4.json
├── output
│ ├── source1.md
│ └── source2.md
├── source1.json
└── source2.json
如果 output
目录不存在,我想生成它们,并且我想从 *.json
生成 *.md
文件> 如果它们不存在,则使用 make
,或者 *.json
已更新。
到目前为止,我有以下Makefile
:
SOURCE_FILES := $(shell find ./ -name "*.json")
OUTPUT_FILES := $(join $(addsuffix output/,$(dir $(SOURCE_FILES))), $(addsuffix .md,$(basename $(notdir $(SOURCE_FILES)))))
.PHONY: all
all: $(OUTPUT_FILES)
$(OUTPUT_FILES): %.md: %.json
mkdir -p $(dir $@)
# Command to create MD file from json file into the output directory here
从 json 文件创建 MD 文件的实际命令在这里并不重要,因为我有一个我将调用的脚本,它将为我执行此操作。这里的问题是,当我尝试运行它时,我得到以下输出:
> make all
make: *** No rule to make target 'anotherdir/output/source4.json', needed by 'anotherdir/output/source4.md'. Stop.
显然,source4.json
不在anotherdir/output
中,而是在前面的目录中,也就是anotherdir
。我不知道如何使模式 $(OUTPUT_FILES): %.md: %.json
正确匹配它。
还是静态模式规则在这里不好?我不确定该怎么做才能适合我的情况。
编辑:我试着做这样的事情:
$(OUTPUT_FILES): %.md: $(join $(subst output,,$(dir %)), $(addsuffix .json,$(basename $(notdir %))))
这不起作用,我仍然得到:
> make all
make: *** No rule to make target 'anotherdir/output/source4.json', needed by 'anotherdir/output/source4.md'. Stop.
编辑 2:为了澄清,我从以下文件开始
.
├── anotherdir
│ ├── source3.json
│ └── source4.json
├── source1.json
└── source2.json
然后当我运行 make 时,我希望它生成这样的输出文件夹
.
├── anotherdir
│ ├── output
│ │ ├── source3.md
│ │ └── source4.md
│ ├── source3.json
│ └── source4.json
├── output
│ ├── source1.md
│ └── source2.md
├── source1.json
└── source2.json
我想使用某种智能 makefile 语法来获取这些文件名,而无需自己进行硬编码。因此,我查看了文档,发现静态模式规则可能是我想要的解决方案,只是我无法获得正确的先决条件模式。
最佳答案
我会这样做:
首先,像您一样找到源文件(稍作改动以防止难看的双斜线):
SOURCE_FILES := $(shell find . -name "*.json")
如果我们可以一次使用两个通配符,一个模式文件会很好,但 Make 不能完全做到这一点。所以我建议使用模板:
define template
TDIR := $(dir $(1))output
TARG := $$(TDIR)/$(notdir $(basename $(1))).md
$$(TARG): $(1)
mkdir -p $$@
@echo building $$@ from $$<
# Command to create MD file from json file into the output directory here
endef
$(foreach SOURCE,$(SOURCE_FILES),$(eval $(call template,$(SOURCE))))
如果这可行,剩下的就是构建一个输出文件列表,以及一个将所有这些文件作为先决条件的默认规则:
define template
TDIR := $(dir $(1))output
TARG := $$(TDIR)/$(notdir $(basename $(1))).md
OUTPUT_FILES += $$(TARG)
$$(TARG): $(1)
mkdir -p $$@
@echo building $$@ from $$<
# Command to create MD file from json file into the output directory here
endef
all:
$(foreach SOURCE,$(SOURCE_FILES),$(eval $(call template,$(SOURCE))))
all: $(OUTPUT_FILES)
它不是很漂亮,但它似乎有效。
关于bash - GNU Make 如何为不在同一目录中的文件制定静态模式规则?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57367690/