3

Is it possible to use makefile variables in prerequisites? My example below is a little backward, but should demonstrate what I'm trying to achieve:

objects_subsystem1 := $(patsubst %.c,%.o,$(wildcard ../src/ss1/*.c))
objects_subsystem2 := $(patsubst %.c,%.o,$(wildcard ../src/ss2/*.c))

all : subsystem1.elf subsystem2.elf

%.elf : $(objects_%)
    $(LD) $< -o $@

EDIT: I'm using GNU Make 3.80 so unfortunately SECONDEXPANSION is not available!

Chris
  • 538
  • 8
  • 19

1 Answers1

3

Yes, if you're using GNUMake:

.SECONDEXPANSION:
%.elf : $$(objects_%)
    $(LD) $< -o $@

EDIT:

As @bobbogo points out, there is a solution that does not require .SECONDEXPANSION. First, we spell out the rules:

objects_subsystem1 := $(patsubst %.c,%.o,$(wildcard ../src/ss1/*.c))
objects_subsystem2 := $(patsubst %.c,%.o,$(wildcard ../src/ss2/*.c))
objects_subsystem3 := $(patsubst %.c,%.o,$(wildcard ../src/ss3/*.c))

all : subsystem1.elf subsystem2.elf subsystem3.elf

subsystem1.elf : $(objects_subsystem1)
    $(LD) $< -o $@
subsystem2.elf : $(objects_subsystem2)
    $(LD) $< -o $@
subsystem3.elf : $(objects_subsystem3)
    $(LD) $< -o $@

Then we rearrange things a little:

objects_subsystem1 := $(patsubst %.c,%.o,$(wildcard ../src/ss1/*.c))
all : subsystem1.elf
subsystem1.elf : $(objects_subsystem1)
objects_subsystem2 := $(patsubst %.c,%.o,$(wildcard ../src/ss2/*.c))
all : subsystem2.elf
subsystem2.elf : $(objects_subsystem2)
objects_subsystem3 := $(patsubst %.c,%.o,$(wildcard ../src/ss3/*.c))
all : subsystem3.elf
subsystem3.elf : $(objects_subsystem3)

%.elf :
    $(LD) $< -o $@

Then we use the eval function:

define RULE_TEMPLATE
objects_subsystem$(1) := $(patsubst %.c,%.o,$(wildcard ../src/ss$(1)/*.c))
all : subsystem$(1).elf
subsystem$(1).elf : $$(objects_subsystem$(1))
endef

$(eval $(call RULE_TEMPLATE,1))
$(eval $(call RULE_TEMPLATE,2))
$(eval $(call RULE_TEMPLATE,3))

%.elf :
    $(LD) $< -o $@

Then finish up with a loop (if it's worth it):

define RULE_TEMPLATE
objects_subsystem$(1) := $(patsubst %.c,%.o,$(wildcard ../src/ss$(1)/*.c))
all : subsystem$(1).elf
subsystem$(1).elf : $$(objects_subsystem$(1))
endef

SUBSYSTEMS := 1 2 3 # this can be made automatic...

$(foreach sys,$(SUBSYSTEMS),$(eval $(call RULE_TEMPLATE,$(sys))))

%.elf :
    $(LD) $< -o $@
Beta
  • 96,650
  • 16
  • 149
  • 150
  • Just the pointer I was looking for. Thanks for providing the answer. – Chris Apr 29 '13 at 07:59
  • Whilst this answer is good it doesn't work in my old version of GNU Make 3.80. Appears to be available from 3.81 onwards: http://www.cmcrossroads.com/article/whats-new-gnu-make-381 Unfortunately my make program is part of a supplier tool chain and not something I can update :( – Chris Apr 29 '13 at 08:52
  • Then a simple `subsystem1.elf: ${objects_subsystem1}` on a line by itself should suffice. If you need a bunch of these then stick it in a loop with `$(eval...)`. – bobbogo Apr 29 '13 at 10:15
  • Could you please elaborate bobbogo. Would each 'one liner' also need the LD command? Yes, I do have a growing bunch of these so want to automate as much as possible. – Chris Apr 29 '13 at 13:55
  • That's fantastic Beta. Thanks for providing such a detailed response :) – Chris Apr 29 '13 at 15:39