为什么这个makefile在'make clean'上执行一个目标, [英] Why does this makefile execute a target on 'make clean'

查看:414
本文介绍了为什么这个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:清除所有

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 -included unconditionally. As far as make knows, they could add dependencies or commands to the clean target. All included 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆