gmake忽略依赖于-include文件的文件

时间:2015-06-10 19:18:52

标签: makefile gnu-make

为了替换我们从另一个项目继承的独立makefile的混乱,实际上使用了make的内容(如this question中所述),我遇到了一个相当不寻常的gmake 3.81忽略无法生成也无法找到的文件的情况。

这是一个演示问题的简短示例文件:

# Remove ALL default rules
.SUFFIXES:
(%): %
%.out: %
%.c: %.w %.ch
%.tex: %.w %.ch
%:: %.v
%:: RCS/%,v
%:: RCS/%
%:: s.%
%:: SCCS/s.%

SOURCES = a.c b.c

OBJS = $(SOURCES:%.c=%.o)

DEPFILES = $(SOURCES:%.c=%.c.d)

EXE = a

.PHONY: all
all: $(EXE)

$(DEPFILES): %.c.d : %.c
        @echo "Determining dependencies for $(<F)"
        @$(CC) -E -MM -MF$@ -MP $<

$(OBJS): %.o: %.c
        @echo "Compiling $(<F)"
        @$(CC) -c $< -o $@

$(EXE): $(OBJS)
        @echo "Linking $(@F)"
        @$(CC) $+ -o $@

# This seems to be the troublemaking line!
-include $(DEPFILES)

如果缺少一个或多个源文件,则不会按预期生成相应的.d文件,源文件未标记为缺失。如果我使用简单的make命令运行此命令,则输出,退出状态为2.

有什么方法可以解决这个问题吗?

哦,虽然在这个例子中看起来很傻,但我在这个项目中确实有几个限制:

  • 我们必须使用gmake 3.81。不允许升级或修补。
  • 完整的makefile构建了一个调试和放大器。发布版本,因此依赖项是单独生成的,一次性生成。结果证明这样简单。
  • 使用静态模式规则似乎很愚蠢,但在大型makefile中它解决了许多问题。
  • 实际系统中实际生成的依赖关系要复杂得多,使用我编写的Perl脚本来按摩英特尔编译器套件的等效输出(再次,需求)到有用的东西。
  • 我已经考虑过预先测试每个文件的存在,但是在生成依赖文件之前,并不是所有文件都是已知的。就目前而言,只有这一个文件而且目录中没有别的东西,没有 shell命令就会被执行。

1 个答案:

答案 0 :(得分:0)

这似乎是gmake 3.81及更高版本中与this bug相关的错误。我已经报告了this specific bug,因为它略有不同。

我选择使用的解决方法受上述链接的启发,如下所示:

# Remove ALL default rules
.SUFFIXES:
(%): %
%.out: %
%.c: %.w %.ch
%.tex: %.w %.ch
%:: %.v
%:: RCS/%,v
%:: RCS/%
%:: s.%
%:: SCCS/s.%

SOURCES = a.c b.c

# WORKAROUND: check for existence of files here
EXISTING_SOURCES = $(wildcard $(SOURCES))
MISSING_SOURCES = $(filter-out $(EXISTING_SOURCES),$(SOURCES))
ifneq "" "$(MISSING_SOURCES)"
$(error Missing source files: $(MISSING_SOURCES))
endif
# END WORKAROUND

OBJS = $(SOURCES:%.c=%.o)

DEPFILES = $(SOURCES:%.c=%.c.d)

EXE = a

.PHONY: all
all: $(EXE)

$(DEPFILES): %.c.d : %.c
    @echo "Determining dependencies for $(<F)"
    @$(CC) -E -MM -MF$@ -MP $<

$(OBJS): %.o: %.c
    @echo "Compiling $(<F)"
    @$(CC) -c $< -o $@

$(EXE): $(OBJS)
    @echo "Linking $(@F)"
    @$(CC) $+ -o $@

# This seems to be the troublemaking line!
-include $(DEPFILES)