Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Design patterns Makefile仅在使用静态模式规则时才重新创建缺少的依赖项文件_Design Patterns_Makefile_Static_Gnu_Rules - Fatal编程技术网

Design patterns Makefile仅在使用静态模式规则时才重新创建缺少的依赖项文件

Design patterns Makefile仅在使用静态模式规则时才重新创建缺少的依赖项文件,design-patterns,makefile,static,gnu,rules,Design Patterns,Makefile,Static,Gnu,Rules,考虑清单1中的makefile代码。目标是为每个对象文件%.o生成一个依赖文件$(DEPDIR)/%.d,该文件是在第9行调用C编译器时生成的。具体来说,依赖项文件是在第9行调用C编译器将%.C文件转换为%.o文件时产生的副作用,即第9行发出两个文件:$(DEPDIR)/%.d和%.o 清单1 现在,用清单2所示的隐式规则替换第8行的静态模式规则,否则其他所有内容保持原样: 清单2 静态模式规则版本认为删除/缺少的先决条件$(DEPDIR)/%.d(在第8行)将由第14行的规则更新(我没有预料到

考虑清单1中的makefile代码。目标是为每个对象文件%.o生成一个依赖文件$(DEPDIR)/%.d,该文件是在第9行调用C编译器时生成的。具体来说,依赖项文件是在第9行调用C编译器将%.C文件转换为%.o文件时产生的副作用,即第9行发出两个文件:$(DEPDIR)/%.d和%.o

清单1

现在,用清单2所示的隐式规则替换第8行的静态模式规则,否则其他所有内容保持原样:

清单2

静态模式规则版本认为删除/缺少的先决条件$(DEPDIR)/%.d(在第8行)将由第14行的规则更新(我没有预料到),从而使%.o目标过期,因此调用第9行的配方来重建%.o文件

另一方面,隐式模式规则显然认为删除/缺少的先决条件$(DEPDIR)/%.d(在第8行)是未更新的最新的(这是我所期望的),因此make认为%.o目标是最新的,第9行的配方没有被调用


那么,隐式模式规则(清单2)为什么不调用第9行的配方行呢?我没有在GNU制作文档中找到任何解释静态模式规则和隐式规则之间的区别。

< P>如果你想理解这一点,你可以考虑阅读。但要解释一下:

静态模式规则之所以有效,是因为第14行:

13  # Ensure make considers missing $(DEPDIR)/%.d files as "not updated"
14  $(DEPDIR)/%.d : ;
这将创建一个隐式规则,说明如何构建一个提供空配方的
.d
文件。配方不起作用,但如果需要运行,它会考虑任何目标取决于它过时。因此,如果文件丢失,make将重建依赖于它的任何目标

删除了原来的错误答案

好吧,现在我自己试过了,并且找到了答案

隐式规则不起作用的原因是考虑了
.d
文件。因为它们是中间文件,如果它们不存在,make不会尝试重建它们,除非出于其他原因需要重建它们;这里没有

您可以先删除所有
.d
文件,然后触摸
.c
文件以强制重建它们,从而证明我的理论是正确的:

$ touch *.c
$ rm deps/*.d
$ make
cc    -c -MT a.o -MMD -MF deps/a.d -o a.o a.c
cc    -c -MT b.o -MMD -MF deps/b.d -o b.o b.c
cc    -c -MT d.o -MMD -MF deps/d.d -o d.o d.c
rm deps/a.d deps/d.d deps/b.d
注意这里的最后一行:删除所有中间文件

如果您查看我上面的博客文章,您会发现我建议将隐式规则更改为显式规则,对您来说,这类似于:

$(SOURCES.c:%.c=$(DEPDIR)/%.d):
现在,所有
.d
文件都是显式目标,因此不能是中间文件


请注意上面提到的博客文章给出了一个更好的处理方法。

< P>如果你想理解这一点,你可以考虑阅读。但要解释一下:

静态模式规则之所以有效,是因为第14行:

13  # Ensure make considers missing $(DEPDIR)/%.d files as "not updated"
14  $(DEPDIR)/%.d : ;
这将创建一个隐式规则,说明如何构建一个提供空配方的
.d
文件。配方不起作用,但如果需要运行,它会考虑任何目标取决于它过时。因此,如果文件丢失,make将重建依赖于它的任何目标

删除了原来的错误答案

好吧,现在我自己试过了,并且找到了答案

隐式规则不起作用的原因是考虑了
.d
文件。因为它们是中间文件,如果它们不存在,make不会尝试重建它们,除非出于其他原因需要重建它们;这里没有

您可以先删除所有
.d
文件,然后触摸
.c
文件以强制重建它们,从而证明我的理论是正确的:

$ touch *.c
$ rm deps/*.d
$ make
cc    -c -MT a.o -MMD -MF deps/a.d -o a.o a.c
cc    -c -MT b.o -MMD -MF deps/b.d -o b.o b.c
cc    -c -MT d.o -MMD -MF deps/d.d -o d.o d.c
rm deps/a.d deps/d.d deps/b.d
注意这里的最后一行:删除所有中间文件

如果您查看我上面的博客文章,您会发现我建议将隐式规则更改为显式规则,对您来说,这类似于:

$(SOURCES.c:%.c=$(DEPDIR)/%.d):
现在,所有
.d
文件都是显式目标,因此不能是中间文件


注意,上面我的博客文章链接提供了一种更好的方法来处理这个问题。

经过进一步的实验,我的原始文章中清单1的问题是第14行:

哎呀。我在想什么!?该行应通过替换引用(或通过调用patsubst等)表示:

或者遵循MadScientist的建议,IMHO提供了更好的可读性(并且我稍微改变了一下,使用OBJ而不是源代码)

在哪里

在更改/修复第14行之后,我的makefile始终调用配方行第9行(在清单1中),为静态模式规则案例和隐式规则案例重建已删除/丢失的依赖项文件

[编辑]


根据MadScientist的评论,我已经从makefile中删除了.PRECIOUS行,因为它不再需要了(在进行上述更改之后),而.PRECIOUS行可能会导致不必要的行为。

在进一步实验之后,我的原始帖子中清单1的问题是第14行:

哎呀。我在想什么!?该行应通过替换引用(或通过调用patsubst等)表示:

或者遵循MadScientist的建议,IMHO提供了更好的可读性(并且我稍微改变了一下,使用OBJ而不是源代码)

在哪里

在更改/修复第14行之后,我的makefile始终调用配方行第9行(在清单1中),为静态模式规则案例和隐式规则案例重建已删除/丢失的依赖项文件

[编辑]

根据MadScientist的评论,我已经从makefile中删除了.PRECIOUS行,因为它不再需要(在进行上述更改之后),而.PRECIOUS行可能会导致不必要的行为。

谢谢。FW
$(SOURCES.c:%.c=$(DEPDIR)/%.d):
$(DEPDIR)/%.d: ;
$(OBJS:%.o=$(DEPDIR)/%.d): ;
DEPFILES := $(OBJS:%.o=$(DEPDIR)/%.d)
$(DEPFILES): ;
OBJS.c := $(SOURCES.c:%.c=%.o)
OBJS.cc := $(SOURCES.cc:%.cc=%.o)
OBJS := $(OBJS.c) $(OBJS.cc)