为什么这个makefile在'make clean'上执行一个目标, [英] Why does this makefile execute a target on '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:清除所有
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会重新生成依赖文件。如何避免这种情况?这不是一个大问题的例子,但对于一个大项目,它可能是相当费时。
谢谢。
$ b $这是因为 .d
文件是 -include $ c $ c> d无条件。只要 make
知道,他们可以添加依赖或命令到 clean
目标。所有包含
d文件是首先构建的,因为这个原因,否则你可能会得到不正确或失败的构建。要禁用此功能,您需要有条件地包含依赖文件: ifneq($(MAKECMDGOALS),clean)
-include $(DEPS)
endif
另一种解决方案是使用 touch
,并将它们替换为实际数据作为编译的副作用。这是automake如何做其依赖关系跟踪,因为它使一次性构建更快。查看 -MD
和 -MMD
选项为 gcc
如果你想去这条路线。使用模式规则:
%d:
@touch $ @
最初创建依赖文件。
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 $< -o $@
%.d: %.cpp
$(CXX) -M $(CXXFLAGS) $< > $@
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.
解决方案 It's because the .d
files are being -include
d unconditionally. As far as make
knows, they could add dependencies or commands to the clean
target. All include
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:
ifneq ($(MAKECMDGOALS),clean)
-include $(DEPS)
endif
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 to gcc
if you want to go this route. Use a pattern rule like:
%.d:
@touch $@
To initially create the dependency files.
这篇关于为什么这个makefile在'make clean'上执行一个目标,的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!