我正在尝试创建一个通用模板来生成规则,构建一组测试用例并将它们放在唯一的目标位置,但是在使用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:
非常感谢任何帮助。
答案 0 :(得分:3)
您可以通过eval
电话取代info
来查找模板有什么问题。
$(foreach testcase, $(TEST_CASES), $(info $(call CHECK_template,$(testcase))))
您的模板很好。但你可能对模式规则有疑问。
来自GNU make manual:
模式规则只有在存在时才能用于构建给定文件 与文件名匹配的目标模式,以及所有先决条件 该规则要么存在,要么可以建立。
也许您在$(ROOT)
目录中没有所需的来源。并且make
无法从模式中为对象文件创建规则。