make pattern自动生成依赖

make pattern to automatically generate dependencies

我想让模式规则为我生成正确的 header 依赖项。我已经尝试这样做了,但是失败了

例如,如果我有文件 foo.cppfoo.hbar.cppbar.hfoo.h 包括 bar.h。使用生成文件:

foo_H=foo.h $(bar_H)
bar_H=bar.h

%.o: %.cpp $(%_H)
    $(CPP) $(CPPFLAGS) $< -o $@

但是当 foo.hbar.h 改变时 make 不会更新。

为什么会失败,如何解决?

这不是 gnu make 的工作方式。

  1. 赋值foo_H时变量bar_H未定义。所以 foo_H 的值只有 foo.h.
  2. 模式扩展在 $(...) 内不起作用。它只会查找不存在的变量 %_H,即为空。
  3. %<%@ 是错误的。您可能打算写 $<$@.
  4. 您的 makefile 至少需要一个非目标。模式规则是不够的。
  5. 除非所有依赖项都存在,否则不会使用模式化规则。这可能不是这里的意图。
  6. 您的模式规则将不适用,因为它搜索 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

看来用模式来实现这种逻辑是死路一条

作为替代方案,我使用 foreachinclude 如下:

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