使用define的通用make规则

时间:2013-08-08 10:44:02

标签: makefile gnu-make

我正在尝试创建一个通用模板来生成规则,构建一组测试用例并将它们放在唯一的目标位置,但是在使用define指令时遇到了一些麻烦。以下是我的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)))  \
)

发出“make check”会出现以下错误

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

如果我在下面手动创建目标规则,则构建时没有错误

../../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:

但是更改以下规则会导致构建错误:

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

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:3)

您可以通过eval电话取代info来查找模板有什么问题。

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

您的模板很好。但你可能对模式规则有疑问。
来自GNU make manual

  

模式规则只有在存在时才能用于构建给定文件   与文件名匹配的目标模式,以及所有先决条件   该规则要么存在,要么可以建立。

也许您在$(ROOT)目录中没有所需的来源。并且make无法从模式中为对象文件创建规则。