我想允许模式规则为我生成正确的标头依赖项。我试过这样做,但它失败了
例如,如果我有文件foo.cpp
,foo.h
,bar.cpp
,bar.h
和foo.h
包含bar.h
。使用Makefile:
foo_H=foo.h $(bar_H)
bar_H=bar.h
%.o: %.cpp $(%_H)
$(CPP) $(CPPFLAGS) $< -o $@
但在foo.h
或bar.h
更改时,make不会更新。
为什么会失败以及如何解决?
答案 0 :(得分:1)
这不是gnu的工作方式。
bar_H
时,变量foo_H
未定义。因此foo_H
只有foo.h
。$(...)
内无效。它只会查找不存在的变量%_H
,即为空。%<
和%@
错了。您可能打算撰写$<
和$@
。foo.c
而不是foo.cpp
。预期的行为是通过
实现的foo.o : foo.h bar.h
bar.o : bar.h
%.o: %.cpp
$(CPP) $(CPPFLAGS) $< -o $@
请注意,依赖项是与可执行命令分开指定的。
另一个注意事项:如果你想摆脱包含依赖性地狱,你可能想看看 cmake 。
答案 1 :(得分:1)
如果您真的想这样做,可以使用secondary expansion:
foo_H = foo.h $(bar_H)
bar_H = bar.h
.SECONDEXPANSION:
%.o: %.cpp $$($$*_H)
$(CPP) $(CPPFLAGS) $< -o $@
答案 2 :(得分:0)
$(%_H)
无法扩展,因为正如
https://www.gnu.org/software/make/manual/html_node/Pattern-Rules.html
Note that expansion using ‘%’ in pattern rules occurs after any variable or function expansions, which take place when the makefile is read
所以似乎使用模式来实现这种逻辑是一个死胡同
作为替代方案,我使用了foreach
和include
,如下所示:
makedep.mk
$(CUR_OBJ): $(CUR_OBJ:.o=.cpp) $($(CUR_OBJ:.o=_H))
$(CXX) $(CXXFLAGS) $(CPPFLAGS) $< -o $@
生成文件
foo_H=foo.h $(bar_H)
bar_H=bar.h
SRCS=foo.cpp bar.cpp
OBJS=$(SRCS:.cpp=.o)
$(foreach obj,$(OBJS),$(eval CUR_OBJ:=$(obj)) $(eval include makedep.mk))
因为只有make变量而没有模式匹配%
所有内容都可以正常扩展