Makefile 使模式自动生成依赖项

Makefile 使模式自动生成依赖项,makefile,gnu-make,Makefile,Gnu Make,我想允许模式规则为我生成正确的头依赖项。我已经试过了,但是失败了 例如,如果我有文件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=foo.H$(bar_H) bar_H=bar.H %.o:%.cpp$(\u H) $(CPP)$(CPPFLAGS)$

我想允许模式规则为我生成正确的头依赖项。我已经试过了,但是失败了

例如,如果我有文件
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=foo.H$(bar_H)
bar_H=bar.H
%.o:%.cpp$(\u H)
$(CPP)$(CPPFLAGS)$<-o$@
但是当
foo.h
bar.h
更改时,make不会更新


为什么会失败?如何修复?

这不是gnu制造的工作方式

  • 赋值
    foo\u H
    时,变量
    bar\u H
    未定义。因此,
    foo_H
    将只具有值
    foo.H
  • 模式扩展在
    $(…)
    内不起作用。它只会查找不存在的变量
    %\u H
    ,即为空

  • %这不是gnu的工作方式

  • 赋值
    foo\u H
    时,变量
    bar\u H
    未定义。因此,
    foo_H
    将只具有值
    foo.H
  • 模式扩展在
    $(…)
    内不起作用。它只会查找不存在的变量
    %\u H
    ,即为空
  • %
    $(\u H)
    无法展开,因为如中所述

    注意,在模式规则中使用“%”进行扩展发生在任何变量或函数扩展之后,这些扩展在读取makefile时发生

    因此,使用模式来实现这种逻辑似乎是一条死胡同

    作为替代,我使用了
    foreach
    include
    ,如下所示:

    makedep.mk

    $(CUR_OBJ): $(CUR_OBJ:.o=.cpp) $($(CUR_OBJ:.o=_H))
        $(CXX) $(CXXFLAGS) $(CPPFLAGS) $< -o $@
    
    由于只有make变量,没有模式匹配
    %
    所有内容都可以正确展开
    $(\u H)
    无法展开,因为如中所述

    注意,在模式规则中使用“%”进行扩展发生在任何变量或函数扩展之后,这些扩展在读取makefile时发生

    因此,使用模式来实现这种逻辑似乎是一条死胡同

    作为替代,我使用了
    foreach
    include
    ,如下所示:

    makedep.mk

    $(CUR_OBJ): $(CUR_OBJ:.o=.cpp) $($(CUR_OBJ:.o=_H))
        $(CXX) $(CXXFLAGS) $(CPPFLAGS) $< -o $@
    

    由于只有make变量,没有模式匹配
    %
    因此,如果您真的想这样做,一切都可以正确展开,您可以使用它:

    foo_H=foo.H$(bar_H)
    bar_H=bar.H
    .第二次扩展:
    %.o:%.cpp$$($$*\u H)
    $(CPP)$(CPPFLAGS)$<-o$@
    
    如果您确实想这样做,您可以使用:

    foo_H=foo.H$(bar_H)
    bar_H=bar.H
    .第二次扩展:
    %.o:%.cpp$$($$*\u H)
    $(CPP)$(CPPFLAGS)$<-o$@
    
    如果您使用的是正统现代编译器(例如GCC或Clang),您可以按照此处描述的步骤自动生成依赖项跟踪:如果您使用的是正统现代编译器(例如GCC或Clang)对于自动生成的依赖项跟踪,您可以按照此处描述的步骤进行操作:我敢肯定,只有在使用
    :=
    时,第1点才是正确的,并且使用
    =
    时会对其进行评估。在我的例子中,第3点是一个打字错误,实际上我写的是正确的。在我的例子中,第4点被省略了,但现在出现了。第5点所有依赖项都存在。第6点也是我的一个输入错误。第2点可能是正确的,但我希望有一种替代语法可以达到同样的效果。我相当确定,只有在使用
    :=
    ,并且使用
    =
    时,第1点才是正确的。在我的例子中,第3点是一个打字错误,实际上我写的是正确的。在我的例子中,第4点被省略了,但现在出现了。第5点所有依赖项都存在。第6点也是我的错别字。第2点可能是正确的,但我希望有一种替代语法可以达到同样的效果
    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))
    
    foo_H = foo.h $(bar_H)
    bar_H = bar.h
    
    .SECONDEXPANSION:
    %.o: %.cpp $$($$*_H)
            $(CPP) $(CPPFLAGS) $< -o $@