我尝试使用 GNU make 构建一个简单的两阶段项目 Makefile。
我想要遵循的逻辑是
- 首先我构建依赖项(通过
gcc -M
) - 我将生成的 .dep 文件包含到第二阶段构建的 Makefile 中。
我的项目的相关部分如下:
MAKEDEP:=$(CXX) $(CXXFLAGS) -M
ALL_SRCS:=$(ALL_OBJS:.o:.cc)
CXX_DEPS:=$(patsubst %.o,.%.dep,$(ALL_OBJS))
-include $(CXX_DEPS)
%.o: %.cc .%.dep
$(CXX) $(CXXFLAGS) -c -o $@ $<
.%.dep: %.cc
$(MAKEDEP) -o $@ $<
clean:
$(RM) -vf $(ALL_OBJS) $(ALL_LIBS) $(ALL_APPS)
dep: $(CXX_DEPS)
一切正常,除了一个例外:如果我运行 a make clean
,它会重建依赖关系!就好像clean: dep
存在一条线而不是一条简单的clean:
线:
$ make clean
g++ -Wall -std=c++11 -M -o .file1.dep file1.cc
g++ -Wall -std=c++11 -M -o .file2.dep file2.cc
g++ -Wall -std=c++11 -M -o .file3.dep file3.cc
rm -vf file1.o file2.o file3.o app
$
背景是什么?为什么在清理之前需要重建依赖关系?我没有给予这样的依赖。
答案1
因为您已要求 make 包含这些文件,所以它会遵循规则来构建它们。
现在我将尝试记住我是如何在我的项目中解决这个问题的:
首先意识到我们第一次并不关心额外的依赖关系,因为无论如何我们都必须构建目标文件。
然后,如果我们添加(或删除)依赖项,我们必须更改我们已经依赖的东西(.cc
现有的或其中之一.h
)。
总之,我们不需要当前状态的完整依赖关系列表,先前状态的依赖关系就足够了。因此,我们可以.dep
在构建 s 的同时构建 s .o
(这也更快,因为只CC
需要一次传递)。
[接下来的一点我不太确定]
现在我们需要引导依赖项:编写一条规则来创建一些虚拟(空).dep
文件(每当.cc
创建 a 时(这可能非常快))。
现在我们仍然需要创建这些虚拟.dep
文件,然后清理它们。如果避免递归 make,则不需要 clean 来解决错误(只需要清理以节省磁盘空间)。
最后一步是添加一级递归(记住递归 make(通常)被认为是有害的)http://lcgapp.cern.ch/project/architecture/recursive_make.pdf)
为干净的规则编写一个简单的 makefile,该文件对另一个 makefile 调用 make 以处理它无法执行的任何规则。
您可能只需要最后一步,但我不会删除答案的开头,因为它向您展示了如何改进 makefile。