我有以下文件和目录结构,其中包含许多文件和目录:
$ 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?
答案 0 :(得分:1)
您的第一个问题来自于如果未明确请求模式规则,则不会创建目标。因此,您需要明确列出要制作的目标。在下面的示例中,它们列在BAMS
make变量中,然后用作all
目标的依赖项,这是makefile的第一个目标。因此,all
是默认目标,输入make
或make all
将构建所有bams
。
您的第二个问题是处理每个R1
目标的R2
和bam
依赖关系。 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还有几个函数(call
,eval
,foreach
),可用于更复杂的示例:
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
变量是规则的框架,可从其对应的bam
和R1
依赖项构建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