https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118223

            Bug ID: 118223
           Summary: Improve autodependency generation to avoid full
                    product build
           Product: gcc
           Version: 11.4.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: other
          Assignee: unassigned at gcc dot gnu.org
          Reporter: th...@harp-project.com
  Target Milestone: ---

Autodependency generation (-MMD) is a nice feature, but there is one
dimension that presents a less-than-spectacular interface for the
user: when a header file that is included in an auto-generated
dependency file for a project is deleted.

Generally when one of a project's header files is deleted, and 'make'
is executed, an unpleasant error is produced:

   make: *** No rule to make target 'hello.h', needed by 'hello.o'.
   make: Target 'hello' not remade because of errors.

This isn't bad on a small project, but on large projects with many
people (who are probably not familiar with the build system), the only
practical resort is to perform a clean, and then rebuild the entire
project.  With large projects, taking long amounts of time to build,
this is objectionable.

If the autodependency generation is output with Gnu Make* in mind,
several options could be used to provide a better result for a user of
the build system (not a developer intimately familiar with the
Makefiles!):

1. Use $(wildcard) to check for the existence of each file, and
   produce an error with instructions on how to clean up:

   Consider, this hello.d:

     hello.o: hello.c hello.h

   It could become:

     $(if $(wildcard hello.h),,$(error hello.h does not exist.   \
         Execute 'rm <path of hello.d>' and reexecute build command.))

   The build would be able to proceed incrementally, and any sources
   still using the missing file would fail with a better error from
   the compiler about the missing file.

2. Set source file to be .PHONY.

   If the header file is not found, using $(wildcard), the source file
   can be set to .PHONY, and it will be automatically out-of-date with
   respect to its output -- for the current invocation of the build
   process only.  It will be rebuilt, and the compiler will produce an
   error that the header cannot be found; this is better than Make
   indicating that the header file cannot be remade.

   This would look something like this, for hello.d:

     $(if $(wildcard hello.h),,.PHONY: hello.c)

     hello.o: hello.c $(wildcard hello.h)

   When the hello.c is updated to no longer reference the deleted
   'hello.h', it will be out-of-date & rebuilt, and then it will be
   up-to-date with respect to 'hello.o'.

Both of these would incur a little bit of extra processing during the
build process, but the overall robustness of the build process would
be improved, and deleting a project's header file would be quickly
repairable (option 1), or self-healing (option 2).

The biggest benefit of this would be all the other team members who
_already_ have 'hello.d', and sync their source tree beyond the
deletion of hello.h; their builds would not be broken, and they would
be able to continue development without having to perform a clean
build.

I believe option 2 is the better choice; deleting the header in the
SCM would require every developer with an already-built project to
provide manual repair, but option 2 just heals the build.


* If Gnu Make is not a requirement for the output of -MMD, then maybe
  -MMDg or something similar could be added to include the Gnu
  Make-specific output.

Reply via email to