【问题标题】:makefile "Removing intermediate files" only sometimesmakefile“删除中间文件”只是有时
【发布时间】:2020-06-10 07:40:24
【问题描述】:

make 正在删除使用我自己的规则(不是隐式规则)创建的文件。

我有一个按预期工作的 makefile,如下所示:


OBJ     = assert.o

DEP     = $(OBJ:.o=.d)

################################################################################
# target: dependencies
#   action

PHONY := all
all: $(subst .a.o,.a.o ,$(join $(OBJ:.o=.a.o),$(OBJ:.o=.so.o)))
    @:


%.d: $(SRC_DIR)/base/assert/%.c
    $(Q)mkdir -p        $(@D)/
    @echo   "   CC -M   build/tmp/base/assert/$@"
    $(Q)$(CC) $(CFLAGS_A) -MG -MT"$@" -MT"$*.a.s" -MT"$*.so.s" -M $< -MF $@
%.a.s: $(SRC_DIR)/base/assert/%.c
    $(Q)mkdir -p        $(@D)/
    @echo   "   CC  build/tmp/base/assert/$@"
    $(Q)$(CC) $(CFLAGS_A) -S $< -o $@
%.so.s: $(SRC_DIR)/base/assert/%.c
    $(Q)mkdir -p        $(@D)/
    @echo   "   CC  build/tmp/base/assert/$@"
    $(Q)$(CC) $(CFLAGS_SO) -S $< -o $@
%.o: %.s
    @echo   "   AS  build/tmp/base/assert/$@"
    $(Q)$(AS) $< -o $@

include $(DEP)


PHONY += clean
clean:
    $(Q)rm -f *.o *.s

################################################################################
# Declare the contents of the .PHONY variable as phony.
.PHONY: $(PHONY)

这个 makefile 创建文件 assert.d assert.a.s assert.so.s assert.a.o 和 assert.so.o 并且不删除它们:

    CC -M   build/tmp/base/assert/assert.d
    CC  build/tmp/base/assert/assert.a.s
    AS  build/tmp/base/assert/assert.a.o
    CC  build/tmp/base/assert/assert.so.s
    AS  build/tmp/base/assert/assert.so.o

然后我有另一个makefile,我必须在其中处理子目录,我必须解决一个问题:% 不能很好地处理。生成文件如下:

OBJ     = $(CURDIR)/tcp/client.o

DEP     = $(OBJ:.o=.d)
BOTH_OBJ    = $(subst .a.o,.a.o ,$(join $(OBJ:.o=.a.o),$(OBJ:.o=.so.o)))
#BOTH_ASM   = $(BOTH_OBJ:.o=.s)

################################################################################
# target: dependencies
#   action

PHONY := all
all: $(BOTH_OBJ)
    @:


$(CURDIR)/%.d: $(SRC_DIR)/base/socket/%.c
    $(Q)mkdir -p        $(@D)/
    @echo   "   CC -M   build/tmp/base/socket/$*.d"
    $(Q)$(CC) $(CFLAGS_A) -MG -MT"$@" -MT"$*.a.s" -MT"$*.so.s" -M $< -MF $@
$(CURDIR)/%.a.s: $(SRC_DIR)/base/socket/%.c
    $(Q)mkdir -p        $(@D)/
    @echo   "   CC  build/tmp/base/socket/$*.a.s"
    $(Q)$(CC) $(CFLAGS_A) -S $< -o $@
$(CURDIR)/%.so.s: $(SRC_DIR)/base/socket/%.c
    $(Q)mkdir -p        $(@D)/
    @echo   "   CC  build/tmp/base/socket/$*.so.s"
    $(Q)$(CC) $(CFLAGS_SO) -S $< -o $@
$(CURDIR)/%.o: $(CURDIR)/%.s
    @echo   "   AS  build/tmp/base/socket/$*.o"
    $(Q)$(AS) $< -o $@

include $(DEP)


PHONY += clean
clean:
    $(Q)rm -rf *.o *.s

################################################################################
# Declare the contents of the PHONY variable as phony.
.PHONY: $(PHONY)


#.PRECIOUS: $(BOTH_ASM)

但是,由于某种原因,make 认为中间文件在这里不重要并删除它们:

    CC -M   build/tmp/base/socket/tcp/client.d
    CC  build/tmp/base/socket/tcp/client.a.s
    AS  build/tmp/base/socket/tcp/client.a.o
    CC  build/tmp/base/socket/tcp/client.so.s
    AS  build/tmp/base/socket/tcp/client.so.o
rm /media/user/DataNTFS/Alex-dev/git/libalx/build/tmp/base/socket/tcp/client.a.s /media/user/DataNTFS/Alex-dev/git/libalx/build/tmp/base/socket/tcp/client.so.s

我找到了this。但是我看不出两个makefile之间没有区别。据我所知,它应该删除它们中的文件或一个都没有。为什么只删除第二个makefile中的文件?


取消注释 .PRECIOUS 似乎可以防止删除,但我不确定我是否隐瞒了一些不好的东西。

【问题讨论】:

  • 旁白:我将添加 .d 文件作为 .s 文件的依赖项:如果标头(例如:.../tcp/client.h)意外删除了 #include它确实需要,我希望编译在那时中断。为此,我需要重新编译 .s,这只能在 .d 是 .s 的依赖项时完成(.d 的包含内容不足以检测到不再使用标头)。

标签: makefile gnu-make


【解决方案1】:

我忘记在gcc生成的依赖文件的目标名称中添加$(CURDIR)/

这一行解决了这个问题:

    $(Q)$(CC) $(CFLAGS_A) -MG -MT"$@" -MT"$(CURDIR)/$*.a.s" -MT"$(CURDIR)/$*.so.s" -M $< -MF $@

所以完整的规则如下:

$(CURDIR)/%.d: $(SRC_DIR)/base/socket/%.c
    $(Q)mkdir -p        $(@D)/
    @echo   "   CC -M   build/tmp/base/socket/$*.d"
    $(Q)$(CC) $(CFLAGS_A) -MG -MT"$@" -MT"$(CURDIR)/$*.a.s" -MT"$(CURDIR)/$*.so.s" -M $< -MF $@

【讨论】:

  • 我不太清楚:你是说这个更正解决了你的问题吗?
  • @JohnBollinger 确实如此。 .s 文件不再被删除,而且我不太了解汇编,但它们对我来说看起来不错。而且我还没有链接,但我想生成的库可以工作。
  • 之前没有删除它们的原因是依赖项(通过include $(DEP) 包含在目标中列出了文件,因此它们不被认为是中间文件。当你有错误的路径时它失败的原因是包含的文件列出了错误的目标,所以你的makefile中的那些被认为是中间的。即使你没有看到这个问题,你最终会意识到make在它的时候并没有重建目标应该,因为依赖项是错误的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-17
  • 2016-02-10
相关资源
最近更新 更多