【问题标题】:makefile: from 3 input generate one outputmakefile:从 3 个输入生成一个输出
【发布时间】:2017-05-25 01:03:58
【问题描述】:

我有这个版本的makefile [sbsuser@compute-00-01 415]$ make --version GNU Make 3.81

我有目录 SOMATIC 我有 3 个文件。我想产生一个只有一个输出。这是我写的。

`

OUTSOMATIC=SOMATIC
FINAL=FINAL
INPUT=$(wildcard $(OUTSOMATIC)/*.vcf)
OUTSORT2= $(patsubst $(OUTSOMATIC)/%.vcf,$(FINAL)/%somatic.ensemble.gz,$(INPUT))
$(info lista $(OUTSORT2))
$(info lista $(INPUT))
.PHONY: all
all: $(INPUT) $(OUTSOMATIC) $(OUTSORT2) $(FINAL)
$(FINAL)/%somatic.ensemble.gz: $(OUTSOMATIC)/%.vcf $(INPUT)
    ~/jdk1.8.0_121/bin/java -XX:+UseSerialGC -Xms1g -Xmx10g -jar /illumina/software/PROG2/bcbio-variation-recall-0.1.7  ensemble  -n 1 $(FINAL)/somatic_ensemble.gz /illumina/software/database/database_2016/hg19_primary.fa $^

`

使用此脚本制作 3 次相同的文件。我不明白如何从输入列表中只创建一个输出以同时使用。 做这个的最好方式是什么? 如果我在$(FINAL)/somatic.ensemble.gz 中更改$(FINAL)/%somatic.ensemble.gz: 我有这个错误:

make: *** No rule to make target FINAL/415_merge_mutect2.somaticsomatic.ensemble.gz', needed byall'。停止`

【问题讨论】:

    标签: makefile gnu-make


    【解决方案1】:

    您可能应该查看 GNU make 手册的介绍部分,其中描述了 make 的工作原理。

    让我们看看你的makefile;首先你定义一些变量。假设您有文件SOMATIC/foo.vcfSOMATIC/bar.vcfSOMATIC/baz.vcf。然后,您创建的变量在展开后将具有这些值:

    OUTSOMATIC = SOMATIC
    FINAL = FINAL
    INPUT = SOMATIC/foo.vcf SOMATIC/bar.vcf SOMATIC/baz.vcf
    

    现在您的 patsubst 会在 INPUT 中找到与模式 SOMATIC/%.vcf 匹配的所有单词,并将其替换为 FINAL/%somatic.ensemble.gz,其中与输入中的 % 匹配的部分将替换为输出:

    OUTSORT2 = FINAL/foosomatic.ensemble.gz FINAL/barsomatic.ensemble.gz FINAL/bazsomatic.ensemble.gz
    

    现在,make 发现您已经定义了一个 all 目标。因为它是 makefile 中的第一个目标,所以这是默认运行的目标。展开后是这样的:

    all: SOMATIC/foo.vcf SOMATIC/bar.vcf SOMATIC/baz.vcf SOMATIC FINAL/foosomatic.ensemble.gz FINAL/barsomatic.ensemble.gz FINAL/bazsomatic.ensemble.gz FINAL
    

    因此,make 将尝试构建 all 目标的所有先决条件,以确保它是最新的。首先它尝试构建SOMATIC/*.vcf 文件。这些文件已经存在,并且 make 没有关于如何重建它们的任何规则,因此它假定它们是最新的。

    接下来它会尝试构建SOMATIC 文件。这是一个目录,它也没有要构建的规则,所以 make 假设它也是最新的。

    接下来 make 尝试构建目标 FINAL/foosomatic.ensemble.gz。让确实有一个可以构建它的规则,你已经创建了一个:

    $(FINAL)/%somatic.ensemble.gz: $(OUTSOMATIC)/%.vcf $(INPUT)
            ~/jdk1.8.0_121/bin/java ...
    

    这与您要构建的目标相匹配,% 值为 foo,因此 make 将先决条件中的 % 替换为 foo 并发现 SOMATIC/foo.vcf 存在且不需要被重建,所以它运行你的食谱。但是,您的配方实际上并没有创建目标FINAL/foosomatic.ensemble.gz;它创建目标FINAL/somatic_ensemble.gz。所以这条规则被打破了,因为它告诉 make 它会做一件事,但它会做另一件事。

    您应该始终确保您的所有配方都构建由自动变量$@ 表示的文件;这将确保您同意您的规则的含义。如果您希望您的配方构建其他文件,那么您的规则编写不正确。

    下一个 make 对 all 的下一个先决条件做同样的事情:FINAL/barsomatic.ensemble.gz。由于该文件不存在,make 尝试使用模式规则构建它,但同样会创建相同的输出文件。

    对于第三个 .gz 文件 FINAL/bazsomatic.ensemble.gz。这就是为什么事情会运行 3 次。

    如果您将模式规则更改为构建 FINAL/somatic.ensemble.gz 的显式规则,这是您想要的,那么 make 无法找到任何方法来构建 all 目标的先决条件,因此会出现此错误。

    您的问题是OUTSORT2 的创建。您只想创建一个输出文件,但您已将OUTSORT2 设置为包含三个不同的文件,因此 make 会尝试创建所有三个文件。你想要这个:

    OUTSOMATIC = SOMATIC
    FINAL = FINAL
    INPUT = $(wildcard $(OUTSOMATIC)/*.vcf)
    OUTSORT2 = $(FINAL)/somatic.ensemble.gz
    
    .PHONY: all
    all: $(OUTSORT2)
    
    $(OUTSORT2): $(INPUT)
            ~/jdk1.8.0_121/bin/java -XX:+UseSerialGC -Xms1g -Xmx10g -jar /illumina/software/PROG2/bcbio-variation-recall-0.1.7  ensemble  -n 1 $@ /illumina/software/database/database_2016/hg19_primary.fa $^
    

    【讨论】:

      猜你喜欢
      • 2019-06-29
      • 1970-01-01
      • 1970-01-01
      • 2016-10-07
      • 2021-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-04
      相关资源
      最近更新 更多