为啥 GNU make 总是重新链接我的项目?

Posted

技术标签:

【中文标题】为啥 GNU make 总是重新链接我的项目?【英文标题】:Why does GNU make always re-link my project?为什么 GNU make 总是重新链接我的项目? 【发布时间】:2014-04-29 17:15:08 【问题描述】:

我在一个充满 .cpp.h 文件的目录中有以下 Makefile:

CFLAGS=-g -std=c++0x -Wall -pedantic -Wextra -D __STDC_LIMIT_MACROS -D __STDC_FORMAT_MACROS -O0
CXX=g++
LDFLAGS=-lgmp -lmathsat -lz3

all: Foo.o Bar.o
        $(CXX) $(CFLAGS) -o myexe Foo.o Bar.o $(LDFLAGS)

depend: .depend

.depend: $(wildcard *.cpp)
        rm -f ./.depend
        $(CXX) $(CFLAGS) -MM $^ > ./.depend

include .depend

%.o: %.cpp
        $(CXX) $(CFLAGS) $(INCLUDE) $< -c

clean:
        rm -f *.o myexe

当我点击make 时,即使.o 文件都没有更改,它也会始终执行最后一步(链接)。我怎样才能防止make 这样做?我希望make 输出Everything up-to-date 或类似的东西。

我在 i686 GNU/Linux 机器上使用 GNU Make 3.82 和 g++ 版本 4.8.2。

【问题讨论】:

【参考方案1】:

Make 重新链接您的项目,因为它尝试构建 allall 的规则不会创建任何名为 all 的文件。相反,它产生myexe。下次你运行 make 时,它​​会发现没有 all,但是有一个构建规则,所以它尽职尽责地执行该规则,每次运行 make 时都会链接 myexe

为了解决您的问题,您需要将您的 makefile 更改为大致如下所示:

all: myexe
    echo Build done

myexe: <myexe dependencies go here>
    $(CXX) $(CFLAGS) -o myexe $(wildcard *.o) $(LDFLAGS)

【讨论】:

请问为什么编辑被拒绝了?我提出这个是为了与问题同步,现在编辑不是指$(wildcard *.o),而是指Foo.o Bar.o。现在的答案看起来好像是 ArtemB 先生建议使用$(wildcard *.o)。我编辑了我的问题,以免给人们带来不好的想法,因为通配符通常是。 @Hinton 对不起,我不知道编辑拒绝。在任何情况下,他们的关键是确保 make 规则生成与规则匹配的文件。您的 myexe 是否具有通配符或显式 .o 文件在很大程度上无关紧要。 完全没有,是给审稿人的意见。您可以尝试自己重做编辑并将$(wildcard *.o) 替换为Foo.o Bar.o,因为通配符仅在.o 文件已经存在时才有效。 您还应该将 'all' 标记为虚假目标(添加一行:.PHONY: all),因为规则不会生成名为 all 的文件。 你是对的,但只要没有人创建文件all,规则就应该可以正常工作。【参考方案2】:

Make 总是尝试构建***规则。对你来说,这是all。由于您的 all 规则实际上并没有创建 all 文件,因此它将始终运行。

您可能希望您的 all 规则成为 myexe 规则,如果您想要明确的 all 规则,请使用仅依赖规则:all: myexe

(使用 GNU Make,您可能希望使用 .PHONY 规则显式声明那些不应生成真实文件的目标。例如 .PHONY: all depend clean。)

【讨论】:

太糟糕了,我不能接受两个答案。 ArtemB 提供了一个代码示例,所以我接受了他的。【参考方案3】:

make 是一个基于规则的专家系统。

你给它一堆规则和一个目标(默认目标是列出的第一个),然后它会构建一个完整的依赖关系树。 如果它们不存在,所有部分都将被重建。递归地比它们的依赖项更早。

您遇到的规则是:因为目标all 没有创建输出文件all,所以make 调用了不存在或过时的规则。

您可以通过使目标all 不执行任何工作而仅依赖于输出文件来纠正此问题。将其标记为.PHONY 也是一个好主意。

【讨论】:

以上是关于为啥 GNU make 总是重新链接我的项目?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Visual Studio 认为我需要构建项目?

指示 gnu make 只使用静态库

如何强制CMake重新链接项目资源变化?

GNU make简要介绍①

如何使用 GNU make 编译多个简单项目

为啥我的就绪函数总是在控制器或指令重新初始化时运行