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

时间:2019-03-02 08:12:25

标签: makefile gnu-make

我有一个数据文件,该文件由脚本处理以产生多个输出文件。这些输出文件中的每一个都将被进一步处理。创建哪些文件取决于输入文件的内容,因此我无法明确列出它们。我不太清楚如何引用Makefile中生成的各种文件。

目前,我有这样的事情:

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文件尚不存在,因此通配符表达式未按我希望的方式替换。我尝试使用通配符功能,但是失败,因为先决条件列表最终为空。

任何指针将不胜感激。

2 个答案:

答案 0 :(得分:1)

编辑:修复了第二遍考试中的先决条件列表。

您显然无法在运行extract_data命令之前计算中间文件列表。在这种情况下,解决方案包括运行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

答案 1 :(得分:0)

不幸的是,您的问题缺少一些详细信息,我会立即询问一些软件开发人员是否会提供此makefile进行审查:

  • extract_files是否提供文件列表?
  • convert_files是转换一个文件还是多个文件?该示例似乎暗示它可以转换多个。
    • 然后我不得不质疑将提取,转换和合并成单独规则的决定,因为无论如何您都不会从并行构建中受益

以下是我会选择的方法。我将使用tar文件作为输入文件的示例,该文件会导致多个输出文件

  • 为文件的排序列表生成makefile片段
    • 使用tar选项v在提取文件时打印文件
    • 将每一行转换为makefile变量赋值
  • 包括用于定义$(DATA_FILES)的片段
    • 如果片段需要重新生成,make将在其生成后重新启动
  • 使用静态模式规则进行转换
  • 将转换后的文件列表用作最终目标的依赖项
.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 $^

更新,如果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 += /') >$@