为什么这个 makefile 在“make clean”上执行目标?
这是我当前的 makefile。
CXX = g++
CXXFLAGS = -Wall -O3
LDFLAGS =
TARGET = testcpp
SRCS = main.cpp object.cpp foo.cpp
OBJS = $(SRCS:.cpp=.o)
DEPS = $(SRCS:.cpp=.d)
.PHONY: clean all
all: $(TARGET)
$(TARGET): $(OBJS)
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) -o $(TARGET)
.cpp.o:
$(CXX) $(CXXFLAGS) -c $< -o $@
%.d: %.cpp
$(CXX) -M $(CXXFLAGS) $< > $@
clean:
rm -f $(OBJS) $(DEPS) $(TARGET)
-include $(DEPS)
除了一个例外,它工作得很好。如果目录已经干净(没有 *.d,*.o)并且我运行“make clean”,它会重新创建依赖项,然后立即删除它们:
[user@server proj]$ make
g++ -M -Wall -O3 foo.cpp > foo.d
g++ -M -Wall -O3 object.cpp > object.d
g++ -M -Wall -O3 main.cpp > main.d
g++ -Wall -O3 -c main.cpp -o main.o
g++ -Wall -O3 -c object.cpp -o object.o
g++ -Wall -O3 -c foo.cpp -o foo.o
g++ -Wall -O3 main.o object.o foo.o -o testcpp
[user@server proj]$ make clean
rm -f main.o object.o foo.o main.d object.d foo.d testcpp
[user@server proj]$ make clean
g++ -M -Wall -O3 foo.cpp > foo.d
g++ -M -Wall -O3 object.cpp > object.d
g++ -M -Wall -O3 main.cpp > main.d
rm -f main.o object.o foo.o main.d object.d foo.d testcpp
[user@server proj]$
我不明白为什么第二个“make clean”会重新- 生成依赖文件。我怎样才能避免这种情况?对于这个人为的示例来说这并不是什么大问题,但对于大型项目来说,这可能非常耗时。
谢谢。
This is my current makefile.
CXX = g++
CXXFLAGS = -Wall -O3
LDFLAGS =
TARGET = testcpp
SRCS = main.cpp object.cpp foo.cpp
OBJS = $(SRCS:.cpp=.o)
DEPS = $(SRCS:.cpp=.d)
.PHONY: clean all
all: $(TARGET)
$(TARGET): $(OBJS)
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) -o $(TARGET)
.cpp.o:
$(CXX) $(CXXFLAGS) -c lt; -o $@
%.d: %.cpp
$(CXX) -M $(CXXFLAGS) lt; > $@
clean:
rm -f $(OBJS) $(DEPS) $(TARGET)
-include $(DEPS)
It works perfectly with one exception. If the directory is already clean (no *.d, *.o) and I run 'make clean', it re-creates the dependencies, then immediately deletes them:
[user@server proj]$ make
g++ -M -Wall -O3 foo.cpp > foo.d
g++ -M -Wall -O3 object.cpp > object.d
g++ -M -Wall -O3 main.cpp > main.d
g++ -Wall -O3 -c main.cpp -o main.o
g++ -Wall -O3 -c object.cpp -o object.o
g++ -Wall -O3 -c foo.cpp -o foo.o
g++ -Wall -O3 main.o object.o foo.o -o testcpp
[user@server proj]$ make clean
rm -f main.o object.o foo.o main.d object.d foo.d testcpp
[user@server proj]$ make clean
g++ -M -Wall -O3 foo.cpp > foo.d
g++ -M -Wall -O3 object.cpp > object.d
g++ -M -Wall -O3 main.cpp > main.d
rm -f main.o object.o foo.o main.d object.d foo.d testcpp
[user@server proj]$
I don't understand why the second 'make clean' would re-generate the dependency files. How can I avoid this? This isn't a big deal for this contrived example, but for a large project, it can be quite time-consuming.
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这是因为
.d
文件被无条件-include
d。据make
所知,他们可以向clean
目标添加依赖项或命令。由于这个原因,所有include
d 文件都会首先构建,否则您可能会得到不正确或失败的构建。要禁用此功能,您需要有条件地包含依赖项文件:另一种解决方案是使用
touch
生成依赖项文件,并将它们替换为实际数据,作为编译的副作用。这就是 automake 进行依赖项跟踪的方式,因为它使一次性构建速度更快。如果您想走这条路,请查看gcc
的-MD
和-MMD
选项。使用如下模式规则:最初创建依赖文件。
It's because the
.d
files are being-include
d unconditionally. As far asmake
knows, they could add dependencies or commands to theclean
target. Allinclude
d files are built first for this reason, otherwise you might get an incorrect or failed build. To disable this, you want to conditionally include the dependency files:An alternative solution is to generate the dependency files using
touch
and have them replaced by actual data as a side-effect of compilation. This is how automake does its dependency tracking, as it makes one-time builds faster. Look into the-MD
and-MMD
options togcc
if you want to go this route. Use a pattern rule like:To initially create the dependency files.
如果您想跳过多个目标的包含,可以使用
filter
函数。If you want to skip the include for multiple targets, you can use the
filter
function.它想要重新生成依赖文件,因为它总是在执行其他操作之前尝试重新生成所有 makefile,包括 -include 的 makefile。 (好吧,实际上,对我来说它并没有这样做 - 我有 GNU Make 3.81 - 所以也许这是你的版本中已修复的错误,或者是我的版本有而你的版本没有的优化。但无论如何。
)解决这个问题的方法是编写规则,以便它们生成 .d 文件作为常规编译的副作用,而不是给出明确的规则来生成它们。这样,当它们不存在时,Make 不知道如何生成它们,因此它不会尝试(在干净的树中,.cpp.o 规则就足够了,您不需要需要 头文件依赖项)。查看 Automake 生成的 makefile(一个简单的文件),看看它是如何完成的。
It wants to regenerate the dependency files because it always tries to regenerate all of the makefiles, including -include'd makefiles, before doing anything else. (Well, actually, for me it doesn't do that - I have GNU Make 3.81 - so maybe it's a bug in your version that was fixed, or an optimization that mine has and yours doesn't. But anyway.)
The easiest way around this is to write your rules so they generate the .d files as a side effect of regular compilation, rather than giving explicit rules to generate them. That way, when they're not there, Make doesn't know how to generate them so it doesn't try (in a clean tree, the .cpp.o rules are enough, you don't need the header file dependencies). Look at an Automake-generated makefile -- a simple one -- to see how it's done.
-include
中的前导-
表示如果依赖项缺失且无法执行,make
不会抱怨被重制,但这并不意味着它不会首先尝试制作它们(并且在这种情况下会成功) - 毕竟,任何有趣或重要的都可以 > 在包含的文件中,让我们尝试制作它们。我认为没有办法阻止这种情况。有关
include
和-include
的文档,请参阅 此处。The leading
-
in-include
means thatmake
won't complain if the dependencies are missing and can't be remade, but it doesn't mean it won't try to make them first (and, in this case, succeed) -- after all, anything interesting or important could be in the included files, whence the let's-try-making them attempt. I don't think there's a way to stop that.For docs on
include
and-include
, see here.