组合makefile的文件导致无目标

时间:2015-10-19 10:48:40

标签: makefile gnu-make

我有以下文件和目录结构,其中包含许多文件和目录:

$ tree
input/
├── C-1-28558666
│   ├── MGRF-C1_S10_L001_R1_001.fastq.gz
│   ├── MGRF-C1_S10_L001_R2_001.fastq.gz
│   ├── MGRF-C1_S10_L002_R1_001.fastq.gz
│   ├── MGRF-C1_S10_L002_R2_001.fastq.gz
│   ├── MGRF-C1_S10_L003_R1_001.fastq.gz
│   ├── MGRF-C1_S10_L003_R2_001.fastq.gz
│   ├── MGRF-C1_S10_L004_R1_001.fastq.gz
│   └── MGRF-C1_S10_L004_R2_001.fastq.gz
├── C-2-28577664
│   ├── MGRF-C2_S11_L001_R1_001.fastq.gz
│   ├── MGRF-C2_S11_L001_R2_001.fastq.gz
│   ├── MGRF-C2_S11_L002_R1_001.fastq.gz
│   ├── MGRF-C2_S11_L002_R2_001.fastq.gz
│   ├── MGRF-C2_S11_L003_R1_001.fastq.gz
│   ├── MGRF-C2_S11_L003_R2_001.fastq.gz
│   ├── MGRF-C2_S11_L004_R1_001.fastq.gz
│   └── MGRF-C2_S11_L004_R2_001.fastq.gz 
...

每个文件名包含R1或R2。 R1和R2的文件属于一起,下面的commanand使用这两个文件和一个dm6.fasta.bwt文件。

bwa mem ref/dm6.fasta.bwt input/C-1-28558666/MGRF-C1_S10_L001_R1_001.fastq.gz input/C-1-28558666/MGRF-C1_S10_L001_R2_001.fastq.gz | samtools view -Sb - > BAMs/C-1-28558666/MGRF-C1_S10_L001.bam

我尝试编写以下Makefile规则:

BAMs/%.bam: $(addsuffix .bwt,${REFERENCE}) $(foreach SIDE,R1 R2, ../MGRF_NGS_KUMARAN-25071046/*/*${SIDE}*.fq.gz )
    bwa mem ${REFERENCE} $(filter %.fq.gz,$^) | samtools view -Sb - > @>

但是,我有:

$ make -n 
make: *** No targets.  Stop.

如何修复上面的Makefile?

1 个答案:

答案 0 :(得分:1)

您的第一个问题来自于如果未明确请求模式规则,则不会创建目标。因此,您需要明确列出要制作的目标。在下面的示例中,它们列在BAMS make变量中,然后用作all目标的依赖项,这是makefile的第一个目标。因此,all是默认目标,输入makemake all将构建所有bams

您的第二个问题是处理每个R1目标的R2bam依赖关系。 GNU make静态模式规则在这种情况下非常有用:

REFERENCE := ref/dm6.fasta
DIRS := $(wildcard input/*)
R1S  := $(foreach dir,$(DIRS),$(wildcard $(dir)/*_R1_001.fastq.gz))
RR1S := $(patsubst input/%_R1_001.fastq.gz,%,$(R1S))
BAMS := $(patsubst %,BAMs/%.bam,$(RR1S))

all: $(BAMS)

$(BAMS): BAMs/%.bam: $(REFERENCE).bwt input/%_R1_001.fastq.gz input/%_R2_001.fastq.gz
    @mkdir -p $(dir $@); \
    bwa mem $^ | samtools view -Sb - > $@

target: target-pattern: prerequisite-pattern是静态模式规则。

GNU make还有几个函数(callevalforeach),可用于更复杂的示例:

REFERENCE := ref/dm6.fasta
DIRS := $(wildcard input/*)
R1S  := $(foreach dir,$(DIRS),$(wildcard $(dir)/*_R1_001.fastq.gz))
RR1S := $(patsubst input/%_R1_001.fastq.gz,%,$(R1S))
BAMS := $(patsubst %,BAMs/%.bam,$(RR1S))

all: $(BAMS)

define BAM_rule
BAMs/$(1).bam: $(REFERENCE).bwt input/$(1)_R1_001.fastq.gz input/$(1)_R2_001.fastq.gz
    @mkdir -p $$(dir $$@); \
    bwa mem $$^ | samtools view -Sb - > $$@
endef

$(foreach r,$(RR1S),$(eval $(call BAM_rule,$(r))))

<强>说明:

RR1S变量列出了所有C-1-28558666/MGRF-C1_S10_L001个词根。然后,它用于构建列出目标的BAMS变量。 BAM_rule变量是规则的框架,可从其对应的bamR1依赖项构建R2目标。 $(1)是使用call函数时将展开的参数:$(call BAM_rule,foo)展开BAM_rule并用$(1)替换所有foo次出现。请注意,某些$符号必须加倍才能通过第一次扩展保留。最后,

$(foreach r,$(RR1S),$(eval $(call BAM_rule,$(r))))

遍历所有词干,并使用eval函数为每个词干实例化一个BAM_rule,由call扩展和专门化。

正常的make扩展会将BAM_rule的每个实例转换为您为给定目标手动编写的规则:

BAMs/C-1-28558666/MGRF-C1_S10_L001.bam: ref/dm6.fasta.bwt input/C-1-28558666/MGRF-C1_S10_L001_R1_001.fastq.gz input/C-1-28558666/MGRF-C1_S10_L001_R2_001.fastq.gz
    @mkdir -p BAMs/C-1-28558666; \
    bwa mem ref/dm6.fasta.bwt input/C-1-28558666/MGRF-C1_S10_L001_R1_001.fastq.gz input/C-1-28558666/MGRF-C1_S10_L001_R2_001.fastq.gz | samtools view -Sb - > BAMs/C-1-28558666/MGRF-C1_S10_L001.bam