gmake ignores files dependent on -include files

124 views Asked by At

In an effort to replace the mess of independent makefiles we inherited from another project with something that actually uses make as it should be (as noted in this question, I've come across a rather unusual situation in which gmake 3.81 ignores files it cannot generate nor can find.

Here's a short sample file that demonstrates the problem:

# 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)

If one or more of the source files is missing, the corresponding .d file is not made, as expected, but the source file is not flagged as missing. If I run this with a simple make command, nothing is output, and the exit status is 2.

Is there any way I can work around this?

Oh, although it seems silly in this example, I do have several restrictions in this project:

  • We must use gmake 3.81. No upgrading or patching allowed.
  • The full makefile builds both a debug & a release version, so dependencies are generated separately, once for all. It turned out to be simpler that way.
  • Using static pattern rules seems silly here, but in the large makefile it solves many problems.
  • The actual generation of dependencies is significantly more complex in the real system, using a Perl script I wrote to massage the equivalent output of the Intel compiler suite (again, a requirement) into something useful.
  • I've thought about pre-testing the existence of every file, but not all of them are known until the dependency files are generated. As it stands, with just this one file and nothing else in a directory, no shell commands get executed.
1

There are 1 answers

0
Joe Sewell On BEST ANSWER

This appears to be a bug in gmake 3.81 and later, related to this bug. I've reported this specific bug, as it is slightly different.

The workaround I've chosen to use is inspired by the above link, is noted below:

# 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)