gnu make“删除中间文件”

Bob*_*Bob 14 makefile gnu-make

我有以下规则

define compile_c
$(ECHO) "CC $<"
$(Q)$(CC) $(CFLAGS) -c -MD -o $@ $<
@# The following fixes the dependency file.
@# See http://make.paulandlesley.org/autodep.html for details.
@# Regex adjusted from the above to play better with Windows paths, etc.
@$(CP) $(@:.o=.d) $(@:.o=.P); \
  $(SED) -e 's/#.*//' -e 's/^.*:  *//' -e 's/ *\\$$//' \
      -e '/^$$/ d' -e 's/$$/ :/' < $(@:.o=.d) >> $(@:.o=.P); \
  $(RM) -f $(@:.o=.d)
endef

vpath %.c . $(TOP)
$(BUILD)/%.o: %.c $(BUILD)/%.pp
    $(call compile_c)

vpath %.c . $(TOP)

$(BUILD)/%.pp: %.c
    $(ECHO) "PreProcess $<"
    $(Q)$(CC) $(CFLAGS) -E -Wp,-C,-dD,-dI -o $@ $<
Run Code Online (Sandbox Code Playgroud)

构建完成后,GNU make 会说
Removing intermediate files...并删除.pp我不想要的所有文件。

为什么要这样做?
我该如何阻止?

Sco*_*eak 20

我认为最好的解决方案是使用.SECONDARY特殊目标。只需添加这一行:

.SECONDARY:
Run Code Online (Sandbox Code Playgroud)

引用手册:

.SECONDARY如果没有先决条件,则所有目标都被视为次要目标(即,不会删除任何目标,因为它被视为中间目标)。

为什么这比将目标作为一次性目标的先决条件更好?这更加混乱,并且必须对可能使用模式规则生成的每组文件显式完成。

为什么这比 更好.PRECIOUS?这会导致文件被保留,即使它们的配方在使用时失败.DELETE_ON_ERROR。后者对于避免失败的配方留下不良输出非常重要,这些输出随后被后续调用视为当前make输出。IMO,你总是想要.DELETE_ON_ERROR,但.PRECIOUS打破了它。

  • @syockit `.SECONDARY: $(%.o)` 似乎工作正常 (2认同)

Ale*_*ing 9

由于您使用的是 GNU Make,您可以对 Makefile 进行以下调整:

.PRECIOUS: $(BUILD)/%.pp  # ADD THIS LINE
$(BUILD)/%.pp: %.c
    $(ECHO) "PreProcess $<"
    $(Q)$(CC) $(CFLAGS) -E -Wp,-C,-dD,-dI -o $@ $<
Run Code Online (Sandbox Code Playgroud)

该文件有这样说.PRECIOUS的指令:

.PRECIOUS依赖的目标被给予以下特殊处理:如果在执行其配方期间 make 被杀死或中断,则目标不会被删除。

[...]

此外,如果目标是一个中间文件,它不会在不再需要后被删除,就像通常所做的那样。

[...]

您还可以列出隐式规则(例如“%.o”)的目标模式作为特殊目标的先决条件文件,.PRECIOUS以保留由目标模式与该文件名匹配的规则创建的中间文件。

这样做的好处是不会创建不需要的附加规则。您尝试做的事情也更清楚:保留重新创建可能很昂贵的宝贵中间文件。

  • 就我个人而言,我会避免使用“.PRECIOUS”,除非它确实是你想要的。它当然不应该用作上面答案中声明目标的随意替代品。仔细考虑文档所说的内容:如果 make 被终止或中断,则目标不会被删除。如果您正在编译一个大文件并使用“^C”怎么办?这会中断 make_并且还会中断你的编译器_。有些编译器会清理半创建的目标,但其他编译器不会。由于半创建的目标具有较新的时间戳,因此 make 不会重新创建它。这可能是一个很难发现的问题。 (4认同)
  • 我将把这个留给后人,但在接下来的几年里,我逐渐同意“.SECONDARY”应该比“.PRECIOUS”更早实现。例如,当您正在积极调试某些内容并且希望在失败时保留部分输出时,“.PRECIOUS”仍然占有一席之地。 (3认同)

Mad*_*ist 8

如果您搜索“gnu make 中间文件”,您将立即在 GNU make 手册部分Chains of Implicit Rules 中找到有关其发生原因的答案。

它还告诉您如何避免它:如果在 makefile 中将文件作为目标或先决条件提及,则该文件不能是中间文件。

因此,只需在.pp某处列出您的文件作为某些规则的先决条件。它不一定是曾经被调用过的规则。您在这里没有提供足够的 makefile 让我们提供完整的答案,但它会是这样的:

all_pps: $(ALL_OBJECTS:.o=.pp)
Run Code Online (Sandbox Code Playgroud)

假设您有一个ALL_OBJECTS包含所有.o文件的变量。

  • 如果我搜索“gnu make middle files”。我找到这个帖子了 该帖子本身就保证了它在 Google 上的成功! (6认同)