Makefile变量的Makefile通配符,用于定义通用规则

时间:2019-09-16 13:13:01

标签: makefile gnu-make

背景,我怀疑XY问题

我在目录中有更简单的C模块。我想在子目录test/中编写这些单元测试。这些单元测试只不过是链接到被测模块的C程序,位于上面的一个目录中。我想要一个Makefile来定义多个构建目标,并让我可以一步或单独构建和运行测试可执行文件。

我尝试的解决方法

我尝试了以下操作:

CC = gcc
CFLAGS = -ggdb -Wall -Wextra -Werror -O3 -std=c99

PARAM_LIST_TARGET = parameter_list_test
PARAM_LIST_SOURCE_FILES = \
    ../parameter_list.c \
    parameter_list_test.c
PARAM_LIST_OBJECT_FILES := $(addsuffix .o,$(basename $(PARAM_LIST_SOURCE_FILES)))

TARGETS = $(PARAM_LIST_TARGET)

all: $(TARGETS)

$(%_TARGET): $(%_OBJECT_FILES)
    $(CC) $(CFLAGS) $^ -o $@

.c.o:
    $(CC) -c $< -o $@ $(CFLAGS)

clean:
    $(RM) *.o $(TARGETS)

test: all
    @for t in $(TARGETS) ; do ./$$t ; done

这是行不通的,这是因为有$(%_TARGET):行。并不奇怪,我没想到它会起作用,但是我希望这可以说明我正在尝试实现的目标。

我想创建更多_TARGET_SOURCE_FILES_OBJECT_FILES形式的块,以测试PARAM_LIST之外的其他模块,例如:

PARAM_LIST_TARGET = parameter_list_test
PARAM_LIST_SOURCE_FILES = \
    ../parameter_list.c \
    parameter_list_test.c
PARAM_LIST_OBJECT_FILES := $(addsuffix .o,$(basename $(PARAM_LIST_SOURCE_FILES)))

OTHER_MODULE_TARGET = other_module_test
OTHER_MODULE_SOURCE_FILES = \
    ../other_module.c \
other_module_test.c
OTHER_MODULE_OBJECT_FILES := $(addsuffix .o,$(basename $(OTHER_MODULE_SOURCE_FILES)))

我知道%适用于文件名,因此尝试在变量上使用它会失败:

$(%_TARGET): $(%_OBJECT_FILES)
        $(CC) $(CFLAGS) $^ -o $@

如何编写一个规则,将Makefile变量_TARGET与其关联的_OBJECT_FILES匹配,而不为每个测试目标创建一个规则?

或更重要的是,我应该怎么做呢?

编辑:我见过this,但似乎每个可执行文件只能使用一个源文件。

2 个答案:

答案 0 :(得分:1)

您始终可以通过构造变量名称来访问make

MY_VAR := "my var"
HIS_VAR := "his var"
HER_VAR := "her var"
CATS_VAR := "cats var"
DOGS_VAR := "dogs var"

ALL_PERSONS := MY HIS HER CATS DOGS
ALL_VARS := $(foreach p,$(ALL_PERSONS),$($(p)_VAR))

$(info $(ALL_VARS))

输出:

$ make
"my var" "his var" "her var" "cats var" "dogs var"

答案 1 :(得分:0)

感谢this answer:单独定义依赖项似乎行得通:

TARGETS = $(PARAM_LIST_TARGET) $(OTHER_MODULE_TARGET)

all: $(TARGETS)

$(PARAM_LIST_TARGET): $(PARAM_LIST_OBJECT_FILES)
$(OTHER_MODULE_TARGET): $(OTHER_MODULE_OBJECT_FILES)

$(TARGETS):
    $(CC) $(CFLAGS) $^ -o $@

这消除了重复规则的需求(每个目标一个)。仍然,每个目标的依赖关系定义看起来都像重复项,对它们的模式匹配会很好。


除此之外,OBJECT_FILES变量变得不必要。这有效:

PARAM_LIST_TARGET = parameter_list_test
PARAM_LIST_SOURCE_FILES = \
    ../parameter_list.c \
    parameter_list_test.c
$(PARAM_LIST_TARGET): $(addsuffix .o,$(basename $(PARAM_LIST_SOURCE_FILES))) # The dependencies directly

将最后一行作为所有目标的一条规则仍然感觉很好。像“对于以TARGET结尾的所有变量,建立对具有相同名称但以SOURCE_FILES结尾的变量内容的依赖”。