GNU makefile 规则和依赖项

Posted

技术标签:

【中文标题】GNU makefile 规则和依赖项【英文标题】:GNU makefile rules and dependencies 【发布时间】:2015-03-13 20:53:55 【问题描述】:

我一直在阅读有关如何编写 makefile 以在 Linux 上构建应用程序的大量阅读,但我对显然实现相同目标的许多不同方法感到非常困惑。

这是我迄今为止想出的建立档案的方法。

SHELL = /bin/sh

CXX = g++
DEBUG = -g
CXXFLAGS = -std=c++11 -Wall -pedantic #-Wextra
CPPFLAGS =  -I. \
            -I./include

SOURCES =   foo1.cpp \
            foo2.cpp \
            foo3.cpp

OBJECTS = $(SOURCES:.cpp=.o)

以下规则成功地将每个源文件编译为目标文件,然后创建存档:

libfoo.a: $(OBJECTS)
    ar rvcs $@ $(OBJECTS)

%.o: src/%.cpp ./include/%.h
    $(CXX) -c $(CPPFLAGS) $(CXXFLAGS) -o $@ $< 

这也做同样的事情:

libfoo.a: $(OBJECTS)
    ar rvcs $@ $(OBJECTS)

$(OBJECTS) : %.o:src/%.cpp
    $(CXX) -c $(CPPFLAGS) $(CXXFLAGS) -o $@ $< 

但是,这会失败并出现错误,即没有规则可以创建目标 'foo1.o:%.h

libfoo.a: $(OBJECTS)
    ar rvcs $@ $(OBJECTS)

$(OBJECTS) : %.o:src/%.cpp %.o:%.h
    $(CXX) -c $(CPPFLAGS) $(CXXFLAGS) -o $@ $< 

有人可以解释为什么它不起作用以及哪种方法最好吗?

第一个选项将头文件列为依赖项,但第二个选项没有。这就是我选择第三个选项的动机。

如何使用选项 2 或 3 将标头列为依赖项?

TIA

【问题讨论】:

【参考方案1】:

您在 try #2 和 try #3 中使用的功能是 static pattern rules,语法如下所示:

<targets...> : <target-pattern> : <prerequisites...>

只能有两个冒号,不能三个。您应该将上面的尝试 #3 写为:

$(OBJECTS) : %.o : src/%.cpp %.h
        $(CXX) -c $(CPPFLAGS) $(CXXFLAGS) -o $@ $< 

注意一件关键的事情:如果您创建了任何.cpp 文件,但没有 有关联的.h 文件,则此规则将失败。只是说说而已。

【讨论】:

谢谢。也就是说,对象依赖于 %.o 替换为 .cpp 和 .h? 哪种方法最好? 手册描述了一个静态模式规则...如果你不明白,请询问一个具体的问题,了解有什么令人困惑的地方。基本上它说“为&lt;targets...&gt; 中列出的每个目标创建一个显式规则,其先决条件与先决条件模式匹配,其中% 是根据目标的匹配构造的”。在手册中更容易理解(IMO)。 我对哪个更好没有强烈的意见。我是一个传统主义者,更喜欢普通的模式规则,但其他人认为静态模式规则更好,因为它们更有效(它们创建显式规则,因此 make 不必进行模式匹配)。两者都有用;它们甚至可以一起使用(模式规则匹配大多数事物,但静态模式规则匹配一些需要不同配方的特定对象)。 感谢您的帮助@MadScientist。我跑偏了,因此延误了。

以上是关于GNU makefile 规则和依赖项的主要内容,如果未能解决你的问题,请参考以下文章

Makefile没有针对目标的规则

makefie文件的基本说明和使用

makefie文件的基本说明和使用

将文件添加到 GNU 依赖项列表?

Makefile文件的基本单元 —— 规则

GNU make:规则专题