生成 GNU Makefile 规则
Generating GNU Makefile Rules
所以在我的项目中我有一个 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 *),$(call rwildcard,$d/,)$(filter $(subst *,%,),$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 函数生成了一个规则,其中目标和依赖项是正确的,但是我得到了一个多目标模式错误。
为什么会出现此错误,我该如何解决?
Why am I getting this error and how can I fix it?
make
中的所有这些 define
和 $(call ...)
生成简单的 字符串 。您必须对其进行评估以使 make
执行您的命令(即创建规则 :
):
$(foreach t,$(src),$(eval $(call objFromSrc,$(patsubst %,obj/%.o,$(basename $(notdir $(t)))),$(t))))
您缺少 $(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 $@
所以在我的项目中我有一个 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 *),$(call rwildcard,$d/,)$(filter $(subst *,%,),$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 函数生成了一个规则,其中目标和依赖项是正确的,但是我得到了一个多目标模式错误。
为什么会出现此错误,我该如何解决?
Why am I getting this error and how can I fix it?
make
中的所有这些 define
和 $(call ...)
生成简单的 字符串 。您必须对其进行评估以使 make
执行您的命令(即创建规则 :
):
$(foreach t,$(src),$(eval $(call objFromSrc,$(patsubst %,obj/%.o,$(basename $(notdir $(t)))),$(t))))
您缺少 $(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 $@