make pattern自动生成依赖
make pattern to automatically generate dependencies
我想让模式规则为我生成正确的 header 依赖项。我已经尝试这样做了,但是失败了
例如,如果我有文件 foo.cpp
、foo.h
、bar.cpp
、bar.h
和 foo.h
包括 bar.h
。使用生成文件:
foo_H=foo.h $(bar_H)
bar_H=bar.h
%.o: %.cpp $(%_H)
$(CPP) $(CPPFLAGS) $< -o $@
但是当 foo.h
或 bar.h
改变时 make 不会更新。
为什么会失败,如何解决?
这不是 gnu make 的工作方式。
- 赋值
foo_H
时变量bar_H
未定义。所以 foo_H
的值只有 foo.h
.
- 模式扩展在
$(...)
内不起作用。它只会查找不存在的变量 %_H
,即为空。
%<
和 %@
是错误的。您可能打算写 $<
和 $@
.
- 您的 makefile 至少需要一个非目标。模式规则是不够的。
- 除非所有依赖项都存在,否则不会使用模式化规则。这可能不是这里的意图。
- 您的模式规则将不适用,因为它搜索
foo.c
而不是 foo.cpp
。
预期的行为是通过
实现的
foo.o : foo.h bar.h
bar.o : bar.h
%.o: %.cpp
$(CPP) $(CPPFLAGS) $< -o $@
请注意,依赖项是与可执行命令分开指定的。
另一个注意事项:如果你想摆脱 include 依赖地狱,你可能想看看 cmake.
$(%_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变量,没有模式匹配%
一切都可以正常展开
如果你真的想这样做,你可以使用 secondary expansion:
foo_H = foo.h $(bar_H)
bar_H = bar.h
.SECONDEXPANSION:
%.o: %.cpp $$($$*_H)
$(CPP) $(CPPFLAGS) $< -o $@
我想让模式规则为我生成正确的 header 依赖项。我已经尝试这样做了,但是失败了
例如,如果我有文件 foo.cpp
、foo.h
、bar.cpp
、bar.h
和 foo.h
包括 bar.h
。使用生成文件:
foo_H=foo.h $(bar_H)
bar_H=bar.h
%.o: %.cpp $(%_H)
$(CPP) $(CPPFLAGS) $< -o $@
但是当 foo.h
或 bar.h
改变时 make 不会更新。
为什么会失败,如何解决?
这不是 gnu make 的工作方式。
- 赋值
foo_H
时变量bar_H
未定义。所以foo_H
的值只有foo.h
. - 模式扩展在
$(...)
内不起作用。它只会查找不存在的变量%_H
,即为空。 %<
和%@
是错误的。您可能打算写$<
和$@
.- 您的 makefile 至少需要一个非目标。模式规则是不够的。
- 除非所有依赖项都存在,否则不会使用模式化规则。这可能不是这里的意图。
- 您的模式规则将不适用,因为它搜索
foo.c
而不是foo.cpp
。
预期的行为是通过
实现的foo.o : foo.h bar.h
bar.o : bar.h
%.o: %.cpp
$(CPP) $(CPPFLAGS) $< -o $@
请注意,依赖项是与可执行命令分开指定的。
另一个注意事项:如果你想摆脱 include 依赖地狱,你可能想看看 cmake.
$(%_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变量,没有模式匹配%
一切都可以正常展开
如果你真的想这样做,你可以使用 secondary expansion:
foo_H = foo.h $(bar_H)
bar_H = bar.h
.SECONDEXPANSION:
%.o: %.cpp $$($$*_H)
$(CPP) $(CPPFLAGS) $< -o $@