如何制作易于更新的makefile?

时间:2011-10-26 17:02:27

标签: 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 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.

# ...

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

  1. 新目标的目标文件列表
  2. 所有目标文件的列表
  3. 制定新目标的目标,即使它使用与其他目标相同的规则
  4. 有没有办法简化这个过程,还是我坚持下去?

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

    $(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.
    

    有没有更好的方法?

3 个答案:

答案 0 :(得分:1)

关于1和2你不能做太多,那些是Make不可能推断的任意事物。你可以稍微提高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))

但它真的值得吗?

答案 1 :(得分:1)

可能有很多方法可以做到这一点。一种这样的方式如下。所有需要为新目标完成的工作都是将其名称添加到模块列表中,并为其提供依赖项列表。

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

答案 2 :(得分:1)

虽然其他答案为手动makefile编写提供了很好的解决方案,但您可以简单地使用automake来简化构建过程。