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命令。

使用-MM生成include指令和依赖生成(make include directive and dependency generation with -MM)的更多相关文章

  1. 转: JSP中include指令和include动作的区别

    include指令是编译阶段的指令,即include所包含的文件的内容是编译的时候插入到JSP文件中,JSP引擎在判断JSP页面未被修改,否则视为已被修改.由于被包含的文件是在编译时才插入的,因此如果 ...

  2. [JSP]JSP中include指令和include动作的差别

    include指令是编译阶段的指令,即include所包括的文件的内容是编译的时候插入到JSP文件里,JSP引擎在推断JSP页面未被改动,否则视为已被改动. 因为被包括的文件是在编译时才插入的.因此假 ...

  3. include指令与jsp:include动作标识的区别

    include指令: 文件包含指令include是jsp的另一条指令标识.通过该指令可以在一个jsp页面中包含另一个jsp页面.不过该指令是静态包含,也就是说被包含文件中所有内容会被原样包含到jsp页 ...

  4. JSP指令--include指令(静态包含)

    转自:https://blog.csdn.net/chentiefeng521/article/details/51802319 include指令         include指令是文件加载指令, ...

  5. makefile自动依赖生成

    自动依赖生成 基于make的构建环境要正确工作, 一个很重要(也很烦人)的任务是, 在makefile中正确列 举依赖. 这个文档将介绍了一个非常有用的让make自身来创建和维护这些依赖的方法. 文章 ...

  6. 【JAVA】使用Eclipse依赖生成jar包时,避免最外层同时生成资源文件的配置。

    使用Eclipse依赖生成jar包时,如果做配置,生成的jar包文件会全部生成在外面,这并不是我们需要的,下面我们一起来修改下配置,使生成的jar包符合我们的需求吧. 1.如果不做任何配置生成的jar ...

  7. 将Qt 动态链接生成的exe及依赖dll打包方法

    源地址:http://blog.csdn.net/ztz0223/article/details/8939341 将Qt 动态链接生成的exe及依赖dll打包方法 原文:http://www.qtcn ...

  8. Javaweb学习笔记——(十二)——————JSP指令:page指令、include指令、taglib指令,JavaBean,内省,EL表达式

    JSP指令JSP指令分类 JSP有三大指令: *page指令 *include指令 *taglib指令 在JSP中没有任何指令是必须的. 但基本上每个JSP都是使用page指令============ ...

  9. 浅谈JSP中include指令与include动作标识的区别

    JSP中主要包含三大指令,分别是page,include,taglib.本篇主要提及include指令. include指令使用格式:<%@ include file="文件的绝对路径 ...

随机推荐

  1. 并发编程 05—— Callable和Future

    Java并发编程实践 目录 并发编程 01—— ThreadLocal 并发编程 02—— ConcurrentHashMap 并发编程 03—— 阻塞队列和生产者-消费者模式 并发编程 04—— 闭 ...

  2. uva 211(dfs)

    211 - The Domino Effect Time limit: 3.000 seconds A standard set of Double Six dominoes contains 28 ...

  3. nginx root&alias文件路径配置

    转:https://www.ttlsa.com/nginx/nginx-root_alias-file-path-configuration/ 总结: alias 改变了访问路径.root对应loca ...

  4. div仿textarea

    CSS代码: .test_box { width: 400px; min-height: 120px; max-height: 300px; _height: 120px; margin-left: ...

  5. MYSQL 基于GTID的复制

    1.概述 从MYSQL5.6 开始,mysql开始支持GTID复制. 基于日志点复制的缺点: 从那个二进制日志的偏移量进行增量同步,如果指定错误会造成遗漏或者重复,导致数据不一致. 基于GTID复制: ...

  6. iOS开发UI篇—字典转模型

    iOS开发UI篇—字典转模型 一.能完成功能的“问题代码” 1.从plist中加载的数据 2.实现的代码 // // LFViewController.m // 03-应用管理 // // Creat ...

  7. IOS开发UI篇—导航控制器属性和基本使用

    IOS开发UI篇—导航控制器属性和基本使用 一.导航控制器的一些属性和基本使用 1.把子控制器添加到导航控制器中的四种方法 (1) 1.创建一个导航控制器 UINavigationController ...

  8. 嵌入式文件I/O操作

    今天把这块的东西算是看完了.总结一下,(1)这里包括底层文件的I/O操作,实际上是系统调用函数借口,是基于文件描述符的文件操作:(2)还有标准I/O操作,是基于缓冲流的文件操作:还有(3)串口的操作, ...

  9. Android - 广播接收者 - BroadcastReceiver

    BroadcastReceiver 介绍: 广播是一种广泛运用的在应用程序之间传输信息的机制 .而 BroadcastReceiver 是对发送出来的广播 进行过滤接收并响应的一类组件 接受一种或者多 ...

  10. MagicalRecord的使用(第三方库实现的数据库)

    MagicalRecord:http://cocoadocs.org/docsets/MagicalRecord/2.1/ 安装: 1.新建一个工程,注意不要勾选 Core Data. 2.利用Coc ...