生成GNU Makefile规则

时间:2019-02-10 03:44:54

标签: gnu-make

所以在我的项目中,我有一个src目录和一个obj目录。我在src目录中递归地找到.c和.cpp文件,然后将其对应的.o文件放到obj目录中。因此,例如,如果我有一个.cpp文件:src/dir1/dir2/file.cpp,则其对应的.o文件将是obj/file.o。然后,我生成一个规则,使用以下代码使用make foreach 函数从.cpp文件中获取.o文件:

rwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2)$(filter $(subst *,%,$2),$d))
src = $(call rwildcard,src/,*.cpp *.c)
obj = $(patsubst %,obj/%.o,$(basename $(notdir $(src))))

$(info src: [$(src)])
$(info obj: [$(obj)])

game.exe: $(obj)
    g++ $^ -o $@

define objFromSrc
$(1): $(2)
    $(info $(1) $(2))
    g++ -c $(2) -o $(1)
endef

$(foreach t,$(src),$(call objFromSrc,$(patsubst %,obj/%.o,$(basename $(notdir $(t)))),$(t)))

以下是一些示例文件的输出:

src: [src/dir/main.cpp src/dir/dir2/other3.cpp src/dir/other2.cpp src/other.c]
obj: [obj/main.o obj/other3.o obj/other2.o obj/other.o]
obj/main.o src/dir/main.cpp
obj/other3.o src/dir/dir2/other3.cpp
obj/other2.o src/dir/other2.cpp
obj/other.o src/other.c
makefile:20: *** multiple target patterns.  Stop.

您可以看到obj变量正确保存了相应的.o文件名。 objFromSrc函数会生成一个目标和依赖关系正确的规则,但是我遇到多个目标模式错误。

为什么会出现此错误,我该如何解决?

2 个答案:

答案 0 :(得分:1)

您缺少$(eval)来解析生成的Makefile代码:

$(eval $(foreach t,$(src),...))

我还建议在多行define的末尾添加一个空行。在$(eval)对动态生成的makefile代码进行编码时,通常会忽略这一点。

define objFromSrc
$(1): $(2)
    $(info $(1) $(2))
    g++ -c $(2) -o $(1)

endef

$(info eval $(foreach t,$(src),...))

奖励代码:您的食谱是常量,因此无需为每个规则重新生成。为$(obj)使用静态模式规则:

.DEFAULT_GOAL := game.exe

obj :=
define objFromSrc
$(1): $(2)
obj += $(1)

endef

$(eval $(foreach t,$(src),...))

$(info obj: [$(obj)])

$(obj): %.o:
    g++ -o $@ -c $<

game.exe: $(obj)
    g++ $^ -o $@

答案 1 :(得分:0)

  

为什么会出现此错误,我该如何解决?

define中的所有这些$(call ...)make都会产生简单的字符串。您必须对其进行评估,以使make达到您的要求(即创建规则$1 : $2):

$(foreach t,$(src),$(eval $(call objFromSrc,$(patsubst %,obj/%.o,$(basename $(notdir $(t)))),$(t))))