使用 -MM 生成包含指令和依赖项 [英] make include directive and dependency generation with -MM

查看:47
本文介绍了使用 -MM 生成包含指令和依赖项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果包含的目标已过期或不存在,我希望包含指令触发构建规则.

I want a build rule to be triggered by an include directive if the target of the include is out of date or doesn't exist.

目前makefile看起来是这样的:

Currently the makefile looks like this:

program_NAME := wget++
program_H_SRCS := $(wildcard *.h)
program_CXX_SRCS := $(wildcard *.cpp)
program_CXX_OBJS := ${program_CXX_SRCS:.cpp=.o}
program_OBJS := $(program_CXX_OBJS)

DEPS = make.deps

.PHONY: all clean distclean

all: $(program_NAME) $(DEPS)

$(program_NAME): $(program_OBJS)
    $(LINK.cc) $(program_OBJS) -o $(program_NAME)

clean:
    @- $(RM) $(program_NAME)
    @- $(RM) $(program_OBJS)
    @- $(RM) make.deps

distclean: clean

make.deps: $(program_CXX_SRCS) $(program_H_SRCS)
    $(CXX) $(CPPFLAGS) -MM $(program_CXX_SRCS) > make.deps

include $(DEPS)

问题在于,似乎 include 指令在构建 make.deps 的规则之前执行,这实际上意味着如果 make.deps 不存在,make 要么没有获得依赖列表,要么总是从中获取 make.deps上一个版本,而不是当前版本.

The problem is that it seems like the include directive is executing before the rule to build make.deps which effectively means that make is either getting no dependency list if make.deps doesn't exist or always getting the make.deps from the previous build and not the current one.

例如:

$ make clean 
$ make
makefile:32: make.deps: No such file or directory
g++  -MM addrCache.cpp connCache.cpp httpClient.cpp wget++.cpp > make.deps
g++    -c -o addrCache.o addrCache.cpp
g++    -c -o connCache.o connCache.cpp
g++    -c -o httpClient.o httpClient.cpp
g++    -c -o wget++.o wget++.cpp
g++      addrCache.o connCache.o httpClient.o wget++.o -o wget++

编辑

我阅读了 包含指令的文档,它听起来如果包含目标不存在,它将继续处理父 makefile 尝试构建目标,但我并不完全清楚这是如何工作的:

I read the docs for the include directive, and it sounds like if the include target doesn't exist it will continue processing the parent makefile try and build the target, but it's not completely clear to me how this works:

如果包含的 makefile 不能在这些目录中的任何一个中找到,生成警告消息,但它不是立即致命的错误;处理包含包括继续.一旦有了读完makefile,make会尝试重新制作任何过时的东西或者不存在.请参阅如何Makefile 被重新制作.只有在它之后试图找到一种方法来重新制作makefile 并失败,将制作将丢失的 makefile 诊断为致命错误.

If an included makefile cannot be found in any of these directories, a warning message is generated, but it is not an immediately fatal error; processing of the makefile containing the include continues. Once it has finished reading makefiles, make will try to remake any that are out of date or don't exist. See section How Makefiles Are Remade. Only after it has tried to find a way to remake a makefile and failed, will make diagnose the missing makefile as a fatal error.

回答

这是对我接受的答案的修改.缺少的一件事是依赖文件也依赖于源文件,除非将它们添加到包含的 deps 文件中,否则它们不会重新生成:

This is a modification of the answer I accepted. The one thing missing was that the dependency files also depend on the sources, and won't get regenerated unless they are added to the deps files which are being included:

%.d: $(program_CXX_SRCS)
    @ $(CXX) $(CPPFLAGS) -MM $*.cpp | sed -e 's@^(.*).o:@1.d 1.o:@' > $@

sed.d 文件的名称添加到每个依赖行的开头,如下所示:

sed adds the name of the .d file to the beginning of each dependency line like so:

foo.d foo.o: foo.cpp foo.h bar.h baz.h

我从这篇关于递归 make 的危险的惊人论文中得到了这个想法:

I got the idea from this amazing paper on the dangers of recursive make:

递归使被认为是有害的

我还将以下内容添加到 makefile:

I also add the following to the makefile:

clean_list += ${program_SRCS:.c=.d}

# At the end of the makefile
# Include the list of dependancies generated for each object file
# unless make was called with target clean
ifneq "$(MAKECMDGOALS)" "clean"
-include ${program_SRCS:.c=.d}
endif

推荐答案

您依赖隐式规则来编译 .cpp 文件.您必须重新定义它以使用将创建依赖文件的 -MM 和 -MF 标志.

You are relying on an implicit rule to compile your .cpp files. You have to redefine it to use the -MM and -MF flags that will create the dependency file.

%.o: %.cpp
    $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@ -MM -MF $@.d

然后,您必须在 Makefile 中包含这些依赖文件,使用 -include 当依赖文件不存在时(第一次或清理后)不会出错.

Then, you have to include these dependencies files in the Makefile, using -include that will not error when the dependencies files do not exist yet (on the first time, or after a clean).

program_DEPS := $(program_OBJS:.o=.o.d)
-include $(program_DEPS)

并且记得在 clean 规则中为依赖文件添加 rm 命令.

And remember to add the rm command for the dependencies files in the clean rule.

这篇关于使用 -MM 生成包含指令和依赖项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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