Makefile 变量的 Makefile 通配符,用于定义通用规则
Makefile wildcard for makefile variables, to define generic rules
后台,我怀疑是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,但似乎每个可执行文件只使用一个源文件。
由于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
将最后一行作为所有目标的一条规则仍然感觉不错。类似于 "for all variables ending with TARGET, build a dependency to the content of the variable with the same name, but ending with SOURCE_FILES instead".
您始终可以通过构造变量的名称来访问 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"
后台,我怀疑是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,但似乎每个可执行文件只使用一个源文件。
由于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
将最后一行作为所有目标的一条规则仍然感觉不错。类似于 "for all variables ending with TARGET, build a dependency to the content of the variable with the same name, but ending with SOURCE_FILES instead".
您始终可以通过构造变量的名称来访问 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"