适用于文件对的Makefile

问题描述 投票:0回答:1

我正在编写 Makefile 来维护工作流程。工作流程的主要部分需要一个可以处理文件对的程序。我有一个包含原始文件对的原始数据目录。每对都有一个名称,后跟

_1.txt
_2.txt
。程序的第一步应该运行一个 QC 管道,该管道需要这两个对并产生新的对。该命令如下所示:

run_qc.sh -in1 file_1.txt -in2 file_2.txt -out1 file_1.qc.txt -out2 file_2.qc.txt

第二步采用质量控制文件并将它们组合成最终结果,如下所示:

run_analysis.sh file_1.qc.txt file_2.qc.txt > file_result.txt

我希望程序针对具有相同前缀的所有对运行(即上例中的

file
是前缀)。到目前为止,我想到的最好的方法是只查看其中一个文件对,然后假设第二个文件对的所有内容都有效,并制定一个虚拟规则,该规则不执行任何操作来填充依赖关系图。看起来像这样:

RAW_DIR = data/raw
QC_DIR = data/qc
ALL_FILES = $(wildcard $(RAW_DIR)/*.txt)
QC_FILES = $(patsubst $(RAW_DIR)/%.txt, $(QC_DIR)/%.qc.txt, $(ALL_FILES))

qc : $(QC_FILES)

$(QC_DIR)/%_1.qc.txt : $(RAW_DIR)/%_1.txt
    RAW1 = $<
    RAW2 = $(patsubst $(RAW_DIR)/%_1.txt, $(RAW_DIR)/%_2.txt)
    QC1 = $@
    QC2 = $(patsubst $(QC_DIR)/%_1.qc.txt, $(QC_DIR)/%_2.qc.txt)

    run_qc.sh -in1 $(RAW1) -in2 $(RAW2) -out1 $(QC1) -out2 $(QC2)

$(QC_DIR)/%_2.qc.txt : $(RAW_DIR)/%_2.txt
    @echo

这个解决方案似乎工作正常,但我认为我缺少一些东西来使工作流程更易于维护,而无需额外的无用目标。我还假设,一旦弄清楚这一步,将结果合并到最终分析步骤中就会容易得多。

所以,最终我的问题是,当我可能必须在许多文件对上运行这个规则时,如何制定一个能够识别这些文件对的规则?

提前致谢,

bash makefile
1个回答
0
投票

您显然认为制作食谱是用“制作语言”之王编写的。不是这种情况。菜谱是 shell 脚本,而您的菜谱不是有效的 shell 语法(

RAW1 = $<
应该是
RAW1=$<
)。

此外,配方的所有行都由不同的 shell 执行。你不能在一行中分配一个变量并在另一行中使用它......除非你将完整的配方编写为单行 shell,如果你愿意的话,还可以继续行。

此外,make 在将配方传递到 shell 之前会扩展它们。因此,如果您希望将

$
符号传递给 shell,则必须转义它 (
$$
),这样,在通过 make 扩展后,它会变成
$

此外,

patsubst
需要3个参数,而不是两个。但你不需要它。
$*
自动变量是你的朋友。

所以,你的规则应该是:

$(QC_DIR)/%_1.qc.txt $(QC_DIR)/%_2.qc.txt: $(RAW_DIR)/%_1.txt $(RAW_DIR)/%_2.txt
    run_qc.sh -in1 $(RAW_DIR)/$*_1.txt  -in2 $(RAW_DIR)/$*_2.txt -out1 $(QC_DIR)/$*_1.qc.txt -out2 $(QC_DIR)/$*_1.qc.txt

GNU make 具有多个目标的模式规则很特殊。它们作为分组目标工作,并且配方仅执行一次即可构建所有目标。使用最新版本的 GNU make,您甚至可以明确这一点:

$(QC_DIR)/%_1.qc.txt $(QC_DIR)/%_2.qc.txt &: $(RAW_DIR)/%_1.txt $(RAW_DIR)/%_2.txt
    run_qc.sh -in1 $(RAW_DIR)/$*_1.txt  -in2 $(RAW_DIR)/$*_2.txt -out1 $(QC_DIR)/$*_1.qc.txt -out2 $(QC_DIR)/$*_1.qc.txt
© www.soinside.com 2019 - 2024. All rights reserved.