0

我正在尝试创建一个通用模板来生成规则,构建一组测试用例并将它们放置在唯一的目标位置,但使用 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:

将不胜感激任何帮助。

4

1 回答 1

3

您可以通过替换evalinfocall 来发现您的模板有什么问题。

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

而且你的模板很好。但是您可能对模式规则有疑问。
GNU 制作手册

仅当存在与文件名匹配的目标模式并且该规则中的所有先决条件都存在或可以构建时,才能使用模式规则构建给定文件。

也许您在$(ROOT)目录中没有必需的源。而且make无法从模式中为目标文件创建规则。

于 2013-08-08T20:32:50.827 回答