开发者社区> double2li> 正文

使用-MM生成include指令和依赖生成(make include directive and dependency generation with -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.
+关注继续查看

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.

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)

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.

For example:

$ 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++

Edit

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:

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.

ANSWER

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 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

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

Recursive Make Considered Harmful

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
解决方案

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

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)

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

本文地址:IT屋 » make include directive and dependency generation with -MM

问 题

如果include的目标已过期或不存在,我想要一个构造规则由include指令触发。



目前makefile像这样:



  program_NAME:= wget ++ 
program_H_SRCS:= $(通配符* .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)
@ - $ (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或者没有依赖列表,如果make.deps不存在或者总是从上一个版本获取make.deps,而不是当前版本



例如:



  $ make clean 
$ make
makefile:32:make.deps:没有这样的文件或目录
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 ++


编辑



我阅读了 include指令的文档,它听起来像包含目标不存在它会继续处理父makefile try和构建目标,但它不是完全清楚我是如何工作:




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



ANSWER



这是我接受的答案的修改。缺少的一个事情是依赖文件也依赖于源,并且不会被重新生成,除非它们被添加到包含的deps文件:



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


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



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


这个惊人的文章对递归make危险的想法:



递归使用有害



我还在makefile中添加以下内容:



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

#在makefile的末尾
#包括为每个生成的依赖列表对象文件
#除非使用目标clean调用
ifneq“$(MAKECMDGOALS)”“clean”
-include $ {program_SRCS:.c = .d}
endif

解决方案

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



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


然后,您必须包括这些依赖文件在Makefile中,使用 -include ,当依赖文件不存在时(第一次或清除后),它不会报错。



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


并记住在清理规则中为依赖文件添加rm命令。


 

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
.NET数据库编程求索之路--7.使用ADO.NET实现(工厂模式-实现多数据库切换)(1)
7.使用ADO.NET实现(工厂模式-实现多数据库切换)(1)     7.1 解决方案框架 解决方案(.sln)包含以下几个项目: (1)类库项目HomeShop.DbUtility,数据访问实用工具; (2)类库项目HomeShop.
767 0
【译】Databricks使用Spark Streaming和Delta Lake对流式数据进行数据质量监控介绍
本文主要对Databricks如何使用Spark Streaming和Delta Lake对流式数据进行数据质量监控的方法和架构进行了介绍,本文探讨了一种数据管理架构,该架构可以在数据到达时,通过主动监控和分析来检测流式数据中损坏或不良的数据,并且不会造成瓶颈。
1431 0
EnjoyCSS – 在线的,先进的 CSS3 代码生成器
  EnjoyCSS 是一款先进的 CSS3 代码生成工具,可以让你摆脱日常的编码。它方便和易于使用的用户界面允许您快速,无需编码就可以调节出丰富的图形样式。您将能够玩转所有的 EnjoyCSS 参数,就像在 Photoshop 或 illustarator 中一样,结合所有可能的 CSS3 样式功能。
1137 0
Package.json中dependencies依赖包中^符号和~符号前缀的区别
刚git了webpack的包发现package.json里面dependencies依赖包的版本号前面的符号有两种,一种是~,一种是^,如下图标记: 然后搜了下在stackoverflow上找到一个比较好的答案所以在此mark下 ~,^的区别是 ~的意思是匹配最近的小版本 比如~1.
873 0
.NET数据库编程求索之路--7.使用ADO.NET实现(工厂模式-实现多数据库切换)(4)
7.使用ADO.NET实现(工厂模式-实现多数据库切换)(4) 7.7 业务逻辑层HomeShop.BLL OrderBiz.cs View Code  1 using System; 2 using System.
801 0
手把手教你生成对抗网络 GAN,50 行代码玩转 GAN 模型!
本文为大家介绍了生成对抗网络(Generate Adversarial Network,GAN),以最直白的语言来讲解它,最后实现一个简单的 GAN 程序来帮助大家加深理解。
1750 0
MyBatis Generator 代码生成器 快速入门指南
要使用MyBatis Generator(MBG)快速启动并运行,请按照下列步骤操作:1、适当地创建并填写配置文件。至少必须指定:一个元素来指定如何连接到目标数据库一个元素来指定生成的Java模型对象的目标包和目标项目用于指定生成的SQL映射文件的目标包和目标项目的元素(可选)一个元素来指定生成的客户端接口和类的目标包和目标项目(如果不希望生成Java客户端代码,则可以省略元素)至少有一个数据库元素有关配置文件的示例,请参阅XML配置文件参考页面。
869 0
+关注
double2li
一个在IT行业摸爬滚打的老司机
2870
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
JS零基础入门教程(上册)
立即下载
性能优化方法论
立即下载
手把手学习日志服务SLS,云启实验室实战指南
立即下载