Reputation: 1437
I have files that look like this
1_0_fa.bam 1_1_fa.bam 1_2_fa.bam 1_3_fa.bam 1_4_fa.bam 1_5_fa.bam
1_6_fa.bam 1_7_fa.bam 1_8_fa.bam 1_9_fa.bam 1_0_mo.bam 1_1_mo.bam
1_2_mo.bam 1_3_mo.bam 1_4_mo.bam 1_5_mo.bam 1_6_mo.bam 1_7_mo.bam
1_8_mo.bam 1_9_mo.bam 1_0_p1.bam 1_1_p1.bam 1_2_p1.bam 1_3_p1.bam
1_4_p1.bam 1_5_p1.bam 1_6_p1.bam 1_7_p1.bam 1_8_p1.bam 1_9_p1.bam
I'd like to combine them by bin, which is the second number in the name. Here is my Makefile (GNU make 3.81)
SHELL = /bin/sh
bins = 0 1 2 3 4 5 6 7 8 9
$(info $(bins))
code = 1
define buildVCF
$(info $(1))
$(eval targ = $(code)_$(1)_bin.vcf)
$(info $(targ))
targs += $(targ)
$(eval deps = $(wildcard $(code)_$(1)_*.bam))
$(info $(deps))
$(targ): $(deps)
cat $$^ > $$@
endef
$(foreach bin,$(bins),$(eval $(call buildVCF,$(bin))))
all: $(targs)
If i do make -n
, it produces
0 1 2 3 4 5 6 7 8 9
0
1_0_bin.vcf
1_0_p1.bam 1_0_mo.bam 1_0_fa.bam
1
1_1_bin.vcf
1_1_fa.bam 1_1_p1.bam 1_1_mo.bam
2
1_2_bin.vcf
1_2_mo.bam 1_2_p1.bam 1_2_fa.bam
3
1_3_bin.vcf
1_3_fa.bam 1_3_mo.bam 1_3_p1.bam
4
1_4_bin.vcf
1_4_mo.bam 1_4_fa.bam 1_4_p1.bam
5
1_5_bin.vcf
1_5_fa.bam 1_5_mo.bam 1_5_p1.bam
6
1_6_bin.vcf
1_6_p1.bam 1_6_fa.bam 1_6_mo.bam
7
1_7_bin.vcf
1_7_fa.bam 1_7_p1.bam 1_7_mo.bam
8
1_8_bin.vcf
1_8_fa.bam 1_8_mo.bam 1_8_p1.bam
9
1_9_bin.vcf
1_9_mo.bam 1_9_p1.bam 1_9_fa.bam
cat 1_0_p1.bam 1_0_mo.bam 1_0_fa.bam > 1_0_bin.vcf
Why is not building the rest of the targets?
Upvotes: 2
Views: 2641
Reputation: 81052
When no target is specified on the command line make builds the default goal.
The default goal is
the first target (not targets whose names start with ‘.’)
In your makefile the first target is the first target created by the buildVCF
define.
As Wintermute points out you can't simply move the all: $(targs)
line above the loop as targs
doesn't have the correct value yet.
That being said you can either put all:
above the loop to "reserve" the default target (in which case all: $(targs)
appends prerequisites to the reserved target) or you can manually set the default goal with .DEFAULT_GOAL := all
anywhere in the makefile.
On a different not I haven't fully understood the setup you have but I would imagine you could do this with a simpler set of general pattern (or static pattern) rules.
Upvotes: 1
Reputation: 44063
Because the all
target isn't the first in the Makefile. When you call make
without a target, the first rule in the Makefile is built, which in this case is the one for 1_0_bin.vcf
(because it is generated first). If you call make -n all
, it'll work as you expect.
To make it work without an explicit rule, just moving the all
target to the top won't work because targs
doesn't have the correct value at that point, but you can make it work using a level of indirection:
all: dummy
define buildVCF
...
endef
$(foreach bin,$(bins),$(eval $(call buildVCF,$(bin))))
dummy: $(targs)
However, this does seem like a rather roundabout way of doing things. If I were you, I'd attempt to solve the problem with a static pattern rule, such as
targs = $(foreach bin,$(bins),$(code)_$(bin)_bin.vcf)
all: $(targs)
$(targs) : $(code)_%_bin.vcf : $(foreach i,fa mo p1,$(code)_%_$(i).bam)
cat $^ > $@
Upvotes: 4