处理从单个输入生成的多个文件
Processing multiple files generated from single input
我有一个数据文件,该文件由脚本处理以生成多个输出文件。然后进一步处理这些输出文件中的每一个。创建哪些文件取决于输入文件的内容,因此我无法明确列出它们。我不太明白如何引用生成文件中生成的各种文件。
目前,我有这样的东西:
final.out: *.out2
merge_files final.out $(sort $^)
%.out2: %.out1
convert_files $?
%.out1: data.in
extract_data data.in
失败 No rule to make target '*.out2', needed by 'final.out'
。我认为这是因为 .out2 文件尚不存在,因此通配符表达式没有按照我希望的方式替换。我尝试使用通配符函数但失败了,因为先决条件列表最终为空。
任何指点将不胜感激。
编辑:修复了第二遍中的先决条件列表。
您显然无法在 运行 执行 extract_data
命令之前计算中间文件列表。在这种情况下,解决方案包括 运行ning make 两次。第一次生成 *.out1
文件,第二次完成作业。您可以使用一个空的虚拟文件来标记是否
extract_data
命令是否再次 运行:
ifeq ($(FIRST_PASS_DONE),)
final.out: .dummy
$(MAKE) FIRST_PASS_DONE=yes
.dummy: data.in
extract_data $<
else
OUT1 := $(wildcard *.out1)
OUT2 := $(patsubst %.out1,%.out2,$(OUT1))
final.out: $(OUT2)
merge_files $@ $(sort $^)
%.out2: %.out1
convert_files $?
endif
很遗憾,您的问题缺少一些细节,我会立即询问是否有软件开发人员会提交此 makefile 以供审核:
extract_files
是否提供文件列表?
convert_files
是转换一个文件还是多个文件?该示例似乎暗示它转换多个。
- 然后我不得不质疑将提取、转换和合并分解为单独规则的决定,因为无论如何您都不会从并行构建中受益
以下是我会选择的方法。我将使用 tar 文件作为输入文件的示例,该文件会产生多个输出文件
- 为排序后的文件列表生成生成文件片段
- 使用
tar
选项 v
在提取文件时打印文件
- 将每一行转换为 makefile 变量赋值
- 包含要定义的片段
$(DATA_FILES)
- 如果片段需要重新生成,make 会在生成后重新tart
- 使用静态模式规则进行转换
- 使用转换后的文件列表作为最终 target
的依赖项
.PHONY: all
all: final.out
# extract files and created sorted list of files in $(DATA_FILES)
Makefile.data_files: data.tar
set -o pipefail; tar xvf $< | sort | sed 's/^/DATA_FILES += /' >$@
DATA_FILES :=
include Makefile.data_files
CONVERTED_FILES := $(DATA_FILES:%.out1=%.out2)
$(CONVERTED_FILES): %.out2: %.out1
convert_files $< >$@
final.out: $(CONVERTED_FILES)
merge_files final.out $^
UPDATE 如果 extract_data
没有提供文件列表,您可以像这样修改我的示例。但这当然取决于您的目录中没有其他匹配 *.out1
的文件。
# extract files and created sorted list of files in $(DATA_FILES)
Makefile.data_files: data.in
set -o pipefail; \
extract_data $< && \
(ls *.out1 | sort | sed 's/^/DATA_FILES += /') >$@
我有一个数据文件,该文件由脚本处理以生成多个输出文件。然后进一步处理这些输出文件中的每一个。创建哪些文件取决于输入文件的内容,因此我无法明确列出它们。我不太明白如何引用生成文件中生成的各种文件。
目前,我有这样的东西:
final.out: *.out2
merge_files final.out $(sort $^)
%.out2: %.out1
convert_files $?
%.out1: data.in
extract_data data.in
失败 No rule to make target '*.out2', needed by 'final.out'
。我认为这是因为 .out2 文件尚不存在,因此通配符表达式没有按照我希望的方式替换。我尝试使用通配符函数但失败了,因为先决条件列表最终为空。
任何指点将不胜感激。
编辑:修复了第二遍中的先决条件列表。
您显然无法在 运行 执行 extract_data
命令之前计算中间文件列表。在这种情况下,解决方案包括 运行ning make 两次。第一次生成 *.out1
文件,第二次完成作业。您可以使用一个空的虚拟文件来标记是否
extract_data
命令是否再次 运行:
ifeq ($(FIRST_PASS_DONE),)
final.out: .dummy
$(MAKE) FIRST_PASS_DONE=yes
.dummy: data.in
extract_data $<
else
OUT1 := $(wildcard *.out1)
OUT2 := $(patsubst %.out1,%.out2,$(OUT1))
final.out: $(OUT2)
merge_files $@ $(sort $^)
%.out2: %.out1
convert_files $?
endif
很遗憾,您的问题缺少一些细节,我会立即询问是否有软件开发人员会提交此 makefile 以供审核:
extract_files
是否提供文件列表?convert_files
是转换一个文件还是多个文件?该示例似乎暗示它转换多个。- 然后我不得不质疑将提取、转换和合并分解为单独规则的决定,因为无论如何您都不会从并行构建中受益
以下是我会选择的方法。我将使用 tar 文件作为输入文件的示例,该文件会产生多个输出文件
- 为排序后的文件列表生成生成文件片段
- 使用
tar
选项v
在提取文件时打印文件 - 将每一行转换为 makefile 变量赋值
- 使用
- 包含要定义的片段
$(DATA_FILES)
- 如果片段需要重新生成,make 会在生成后重新tart
- 使用静态模式规则进行转换
- 使用转换后的文件列表作为最终 target 的依赖项
.PHONY: all
all: final.out
# extract files and created sorted list of files in $(DATA_FILES)
Makefile.data_files: data.tar
set -o pipefail; tar xvf $< | sort | sed 's/^/DATA_FILES += /' >$@
DATA_FILES :=
include Makefile.data_files
CONVERTED_FILES := $(DATA_FILES:%.out1=%.out2)
$(CONVERTED_FILES): %.out2: %.out1
convert_files $< >$@
final.out: $(CONVERTED_FILES)
merge_files final.out $^
UPDATE 如果 extract_data
没有提供文件列表,您可以像这样修改我的示例。但这当然取决于您的目录中没有其他匹配 *.out1
的文件。
# extract files and created sorted list of files in $(DATA_FILES)
Makefile.data_files: data.in
set -o pipefail; \
extract_data $< && \
(ls *.out1 | sort | sed 's/^/DATA_FILES += /') >$@