生成GNU Makefile规则 [英] Generating GNU Makefile Rules

查看:101
本文介绍了生成GNU Makefile规则的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

So in my project I have a src directory and an obj directory. I'm recursively finding the .c and .cpp files in my src directory, and then its corresponding .o file gets put right in the obj directory. So for example if I have a .cpp file: src/dir1/dir2/file.cpp, its corresponding .o file would be obj/file.o. Then I'm generating the rule to get the .o file from the .cpp file using a make foreach function using this code:

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)))

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

Here is the output for some example files:

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函数会生成一个目标和依赖关系正确的规则,但是我遇到多个目标模式错误.

You can see the obj variable correctly holds the corresponding .o file names. And the objFromSrc function generates a rule where the target and dependency are correct, but yet I get a multiple target patterns error.

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

Why am I getting this error and how can I fix it?

推荐答案

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

You are missing the $(eval) to parse the generated makefile code:

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


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


I would also suggest to add an empty line at the end of the multi-line define. Leaving this out is usually calling for trouble when $(eval)uating dynamically generated makefile code.

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

endef

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


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


BONUS CODE: your recipe is a constant so there is no need to re-generate it for every rule. Use a static pattern rule for $(obj) instead:

.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 $@

这篇关于生成GNU Makefile规则的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆