具有多个源的顶级目录Makefile

时间:2012-08-06 15:43:24

标签: makefile gnu-make

我有一个项目,其中我需要使用Makefile使目录层次结构为

[user@machine program]$ ls
bin  build  CHANGELOG  Makefile  src

到目前为止,我创建这样一个Makefile的尝试一直没有结果。这是我的想法:

1)定义一些有希望的有用的东西

SRCDIR    =$(PWD)/src    # Keep multiple *.cpp and *.h files in here
BUILDDIR  =$(PWD)/build  # Build all appropriate *.o files
BINDIR    =$(PWD)/bin    # Compile/link all *.o files for final executable

PROJ      = program      #This is the name of the final executable

然后定义其他内容,如编译器,一些库链接等(我不担心这些)。

2)所有目标:

all: $(BINDIR)/$(PROJ)

3)所有目标的依赖关系:

$(BINDIR)/$(PROJ): $(BUILDDIR)/%.o
    $(CPP) $^ -o $@

4)最后,* .cpp文件

$(BUILDDIR)/%.o: $(SRCDIR)/%.cpp $(SRCDIR)/%.h
    $(CPP) -c $(CFLAGS) $<

5)究竟发生了什么?

[user@machine program]$ make
make: *** No rule to make target `/home/user/program/build/%.o', needed by `/home/user/program/bin/program'.  Stop.

所以我觉得我目前的错误是我的最终可执行文件的规则,但我不确定如何修复它。

对此有何想法?任何输入都非常感谢!

1 个答案:

答案 0 :(得分:2)

是的,你是对的。在第三步($(BINDIR)/$(PROJ): $(BUILDDIR)/%.o)中,您混合了显式和隐式规则。

您必须以某种方式提供将它们链接在一起的对象列表。最常见的方法是将所有现有源文件的名称(请参阅wildcard函数)转换为相应的目标文件或明确列出它们。

SRCS := $(wildcard $(SRCDIR)/*.cpp)
OBJS := $(SRCS:$(SRCDIR)/%.cpp=$(BUILDDIR)/%.o)

现在您的链接规则应如下所示:

$(BINDIR)/$(PROJ): $(OBJS)
    $(CPP) $^ -o $@

几点注释:

  1. 通常CPP变量名代表C PreProcessor,C ++编译器代表CXX。来自GNU Make manual

      

    CC编制C程序的程序;默认‘cc’

         

    CXX编译C ++程序的程序;默认‘g++’

         

    CPP用于运行C预处理器的程序,其结果为标准输出;默认‘$(CC) -E’

  2. 仅添加$(SRCDIR)/%.h先决条件并不能保证增量构建的完整性。假设foo.cpp包括foo.hbar.cpp包括bar.hfoo.h。然后修改foo.h只会触发foo.cpp的编译,但是您可能会期望bar.cpp也会被重新编译。不要尝试手动跟踪标头依赖关系,而是使用Advanced Auto-Dependency Generation文章中描述的方法之一。我还在我的earlier answers中描述了其中一个。