Dushara
Dushara

Reputation: 668

Generic make rules using define

I'm trying to create a common template to generate rules build a set of test cases and place them in unique target locations but have hit a bit of snag with the define directive. The following is the relevant section of my Makefile:

ROOT=../..
PLATFORM=akyboard_gcc

# include all the test cases for the current platform
# They add to the TEST_CASES variable
TEST_CASES=A B
A_FILES = a1.c a2.c
B_FILES = b1.c b2.c

check: $(TEST_CASES:%=check_%)

define CHECK_template

# build artifact directories
$(1)_BLDDIR=$(ROOT)/build/$(PLATFORM)/$(1)
$(1)_OBJDIR=$$($(1)_BLDDIR)/obj
$(1)_EXEDIR=$$($(1)_BLDDIR)/exe

# prepend src/ to all the files that are part of the test case
$(1)_FILES := $($(1:%=%_FILES):%=src/%)

# add the test runner as one of the files to be compiled
$(1)_FILES += test_runner/$(PLATFORM)/main.c

# construct list of objects generated by sources
$(1)_OBJ = $($(1)_FILES:%.c=$$($(1)_OBJDIR)/%.o)

# This creates a rule such as check_{test_case}:
check_$(1): $$($(1)_OBJ)
    @echo 1 $(1)
    @echo 2 $$($(1)_FILES)
    @echo 3 $$($(1)_OBJ)
    @echo 5 $$($(1)_OBJDIR)
    @echo 4 $$($(1)_BLDDIR)
    @echo 6 $$($(1)_EXEDIR)

$$($(1)_OBJDIR)/%.o: $(ROOT)/%.c
    @echo coconut

endef

$(foreach testcase, $(TEST_CASES),              \
    $(eval $(call CHECK_template,$(testcase)))  \
)

Issuing "make check" gives the following error

*** No rule to make target `../../build/akyboard_gcc/A/obj/a1.o', needed by `check_A'.  Stop.

If I manually create the target rules below it builds without errors

../../build/akyboard_gcc/A/obj/a1.o:
../../build/akyboard_gcc/A/obj/a2.o:
../../build/akyboard_gcc/B/obj/b1.o:
../../build/akyboard_gcc/B/obj/b2.o:

But changing rules like below causes the build error:

../../build/akyboard_gcc/A/obj/%.o:

Would be grateful for any help.

Upvotes: 0

Views: 1509

Answers (1)

Nikolai Popov
Nikolai Popov

Reputation: 5685

You can find what wrong with your template by replacing eval with info call.

$(foreach testcase, $(TEST_CASES), $(info $(call CHECK_template,$(testcase))))

And your template is fine. But you probably have a problem with pattern rules.
From GNU make manual:

A pattern rule can be used to build a given file only if there is a target pattern that matches the file name, and all prerequisites in that rule either exist or can be built.

Perhaps you don't have required sources in $(ROOT) directory. And make just can't create a rule for object file from pattern.

Upvotes: 3

Related Questions