如何制作易于更新的makefile?

如何制作易于更新的makefile?,makefile,extensibility,maintainability,Makefile,Extensibility,Maintainability,我的makefile如下所示: FOO_OBJECT_FILES := $(OBJDIR)/Foo.cpp.o BAR_OBJECT_FILES := $(OBJDIR)/Bar.cpp.o $(OBJDIR)Bar.c.o ALL_OBJECT_FILES := $(FOO_OBJECT_FILES) $(BAR_OBJECT_FILES) $(BINDIR)/Foo.a: $(FOO_OBJECT_FILES) # Rules for making a static library

我的makefile如下所示:

FOO_OBJECT_FILES := $(OBJDIR)/Foo.cpp.o
BAR_OBJECT_FILES := $(OBJDIR)/Bar.cpp.o $(OBJDIR)Bar.c.o
ALL_OBJECT_FILES := $(FOO_OBJECT_FILES) $(BAR_OBJECT_FILES)

$(BINDIR)/Foo.a: $(FOO_OBJECT_FILES)
    # Rules for making a static library out of Foo's object files go here.

$(BINDIR)/Bar.a: $(BAR_OBJECT_FILES)
    # This uses the exact same command sequence as the previous rule.

$(BINDIR)/All.a: $(ALL_OBJECT_FILES)
       # Ditto.

# ...
当(如果)向项目中添加更多目标时,开发人员必须至少更新三件事:

  • 新目标的对象文件列表
  • 所有对象文件的列表
  • 用于创建新目标的目标,即使它使用与其他目标相同的规则
  • 有没有办法简化这个过程,还是我一直坚持

    我尝试过使用通配符规则,但看起来它们不适用于宏

    $(BINDIR)/%.a: $(%_OBJECT_FILES)
        # ...
    
    您可以将对象文件列表视为规则,但最终的目标规则无法直接访问它们

    OBJECT_FILES_Foo: $(OBJDIR)/Foo.cpp.o
    OBJECT_FILES_Bar: $(OBJDIR)/Bar.cpp.o $(OBJDIR)Bar.c.o
    OBJECT_FILES_All: FOO_OBJECT_FILES BAR_OBJECT_FILES
    
    $(BINDIR)/%.a: OBJECT_FILES_%
        # This rule can't see into the object file lists to use them to build.
    

    没有更好的方法了吗?

    关于1和2,你做不了太多,这些都是武断的事情,不可能推断出来。您可以稍微改进3:

    $(BINDIR)/%.a:
        # commands for making a static library
    
    # adding a new target:
    QUARTZ_OBJECT_FILES := $(OBJDIR)/Quartz.cpp.o $(OBJDIR)Arbitrary.o
    ALL_OBJECT_FILES += $(QUARTZ_OBJECT_FILES) 
    $(BINDIR)/Quartz.a: $(QUARTZ_OBJECT_FILES)
    
    您可以使用模板将这三行减为一行:

    $(eval $(call template, QUARTZ_OBJECT_FILES, $(OBJDIR)/Quartz.cpp.o $(OBJDIR)Arbitrary.o))
    

    但这真的值得吗?

    可能有很多方法可以做到这一点。其中一种方法如下。对于一个新目标,需要做的就是将其名称添加到模块列表中,并给出它的依赖项列表

    BINDIR := bin OBJDIR := obj MODULES := Foo Bar Foo_OBJS := $(OBJDIR)/Foo.cpp.o Bar_OBJS := $(OBJDIR)/Bar.cpp.o $(OBJDIR)/Bar.c.o ##################################################### # # # Nothing below here should need to be altered. # # # ##################################################### All_OBJS := $(foreach mod, $(MODULES),$($(mod)_OBJS)) define rule $(BINDIR)/$(1).a: $($(1)_OBJS) @echo @echo 'Target: $$@' @echo 'Deps : $$^' endef $(foreach lib, All $(MODULES), $(eval $(call rule,$(lib)))) ########################################### # # # The next part is just here for testing. # # # ########################################### .PHONY: all all: $(foreach lib, All $(MODULES),$(BINDIR)/$(lib).a) %.o: @echo Making $@ BINDIR:=bin OBJDIR:=obj 模块:=Foo-Bar Foo_OBJS:=$(OBJDIR)/Foo.cpp.o Bar_OBJS:=$(OBJDIR)/Bar.cpp.o$(OBJDIR)/Bar.c.o ##################################################### # # #下面的内容不需要修改# # # ##################################################### 所有对象:=$(每个模块,$(模块),$($(模块)\u对象)) 定义规则 $(BINDIR)/$(1.a:$($(1)_OBJS) @回音 @echo“目标:$$@” @回显'Deps:$$^' 恩德夫 $(foreach lib,所有$(模块),$(eval$(调用规则,$(lib))) ########################################### # # #下一部分仅用于测试# # # ########################################### 冒牌货:全部 全部:$(foreach lib,所有$(模块),$(BINDIR)/$(lib.a) %.o: @回声制造$@
    虽然其他答案为手工编写makefile提供了很好的解决方案,但您可以简单地使用automake来简化构建过程。

    “没有更好的方法吗?”-这不是创建automake的目的吗?我认为您可以通过在递归调用make之前设置一些变量来实现这一点,但我认为这并不简单或更好。