[Bug other/118223] New: Improve autodependency generation to avoid full product build

2024-12-27 Thread thutt--- via Gcc-bugs
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 ' 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.

[Bug other/118223] Improve autodependency generation to avoid full product build

2024-12-29 Thread thutt--- via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118223

Thutt  changed:

   What|Removed |Added

 Resolution|WONTFIX |---
 Status|RESOLVED|UNCONFIRMED

--- Comment #7 from Thutt  ---
> I don't see this as a big issue.  Note I originally misunderstood
> the issue you were talking about. You are saying if you delete a
> header file that was used originally and now you need to rebuild
> everything.

I think you've misunderstood the impact, and the benefit of updating
Gcc to be more friendly to developers who can, and do, encounter the
Make error that this ticket is intended to remove.  Allow me to
provide some emphasis:

o Few developers understand the build process.

  Expecting developers to understand all build tools quirky behavior
  is a tall order, given that a vanishingly small percentage know
  anything about the build software, and even less know anything about
  how the build process is actually implemented using the build
  software.

  When a developer encounters an error produced by Make, it's 100%
  believed to be caused by the build system; a build failure.  In the
  case described here, the error produced by Make:

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

  is actually caused because of Gcc's simplistic auto dependency
  generation model.  Due to the paucity of information Make produces,
  the only rational course of action is a full clean build -- even if
  uses of 'hello.h' have been fully purged from the source tree; the
  build cannot be (easily!) repaired.

  If Gcc were updated just a tad, the build process would be
  self-healing and this class of error would be forever banished.

  This would be a net win for developers:

   + A clean build would not be needed in these cases

   + Make will not show indecipherable messages to people who don't
 know Make nor the build process.

o Large software projects are an amalgam

  Every one of the large projects I currently work on take at least an
  hour to perform a full build.  50% of them take SEVERAL hours to
  perform a full build.  Performing a full build is a major
  productivity hit for the day.

  Different parts of the software are built with different tools.
  Make, Maven, Gradle, Go, CMake, Scons, Bazel, and more.  There is a
  top-level coordinating process that puts everything together,
  barely (see above how few people know how build systems work).

  Inducing completely unrelated software to be fully re-built because
  a header file for C code has bee deleted is a major productivity
  killer.  Gcc can be a better citizen and eliminate the requirement
  to unnecessarily rebuild software.

o Not all headers are system-global.

  Some headers are private to the sub-system which uses them, while
  others are public and can be used by everyone.

  As above, deleting a non-public header should not require everyone
  else to rebuild their entire software -- but that's what's required
  with the status quo, though it can be fixed.


> Large projects have handled this always by just make clean and
> rebuild. Incremental builds should only be used for small
> developmental changes. You should always do a full rebuild just in
> case there is some stale changes left behind in a large project.

That is just another telling of the "true Scotsman" fallacy.

A build system does NOT distinguish between a "full" build and an
"incremental" build.  A build system simply determines what software
is out-of-date with respect to artifacts, and rebuilds those pieces.
If invoking the build system with no artifacts present, and all
artifacts present, produces different results, then the build system
is non-deterministic and flawed.

It is possible to have a build process that is correct in Make (Netapp
did it, at great expense).  Generally, however "good enough" is where
things stand.  With the proposed change, the bar for "good enough" is
automatically raised and all uses of auto dependency generation with
Gcc will benefit with fewer broken incremental builds.

(As an aside,, newer build systems (such as Bazel (not a fan)) force
much more work upfront on the developer so that these incremental
build issues do NOT happen.)

> GCC for an example always requires you do a full bootstrap to make
> sure nothing gets miscompiled. I am not seeing why this is a huge
> problem in general.

If something is mis-compiled in an incremental build, then the build
process is non-deterministic and flawed; it should be fixed.

I would prefer to not use a flawed build process as a defense of why
an improvement to auto dependency generation should not be undertaken.
Do you agree?

You've rejected this suggestion and closed this ticket because the
status quo is satisfactory to you.

It would be much better if you could discuss th