处理从单个输入生成的多个文件

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 += /') >$@