A major problem when debugging the build system is figuring out what makefiles 
are evaluated, and in which order. 

Our makefiles comes in three flavors, which I have termed "files", "includes" 
and "snippets", for the purpose of being able to reason about them. The 
difference is this:
* "files" (that is, "top-level files") are run directly by calling `make -f 
FooFile.gmk`
* "includes" are included by other makesfiles using `include FooInclude.gmk`
* "snippets" are automatically included by the framework, based on special 
naming rules

This patch adds a systematic structure to files, includes and snippets, which 
allows for a logging framework to be attached.

The log will look something like this:


:Enter Main.gmk
:    Enter common/MakeBase.gmk [include]
:         Enter common/Utils.gmk [include]
:         Leave common/Utils.gmk
:         Enter common/FileUtils.gmk [include]
:         Leave common/FileUtils.gmk
:    Leave common/MakeBase.gmk
:    Enter MainSupport.gmk [include]
:    Leave MainSupport.gmk
:    Enter common/FindTests.gmk [include]
:    Leave common/FindTests.gmk
:    Enter common/Modules.gmk [include]
:    Leave common/Modules.gmk
:Leave Main.gmk [now executing rules]


Furthermore, this patch achieves a secondary benefit, which is arguably just as 
important, and that is simplifying the boilerplate in makefiles. I am not 
saying that it offers strictly *less* boilerplate -- in some cases, it is 
actually more than what we have right now. But it does offer *systematic* 
boilerplate. You only have to include the proper start/end makefile and then 
you're good to go. These start/end files implements the best practices that 
have evolved over the year (like include guards for includes), and standards we 
employ in the JDK build system (like always starting with a `default: all` 
rule). It became painfully obvious when implementing this PR that our adherence 
to these best practices are sketchy, at best. From now on, it will not be 
possible to miss declaring best practice boilerplate, since it is all 
concentrated in a single set of files.

While updating all makefiles to use these new systematic start/end includes, I 
took the opportunity to clean up the style used and make it more consistent. So 
now all makefiles follows this pattern (as far as applicable):

include Make[File/Include]Start.gmk

################################################################################
# High-level description of this file (if present).
################################################################################

include Foo.gmk # includes ordered alphabetically
include Zoo.gmk

... actual code

$(TARGETS) += my-targets ...

################################################################################

include Make[File/Include]End.gmk


This new framework also allows for systematic inclusion of custom makefile 
snippets, which were previously not possible. A side effect of this is that 
some custom include file names have changed, and the actual place where it is 
included has changed to the very top or bottom, which was not always the case. 
This change in placement made it necessary to adapt some code so that the hooks 
could still work. I have updated the corresponding Oracle closed source, but if 
there are some other company or organization that uses custom makefile 
snippets, they might have to adapt your custom sources. I will announce this in 
a separate mail to `build-dev` before integration, since it is a potentially 
breaking change.

I have been wrestling with this patch from time to time, over a long period of 
time. I have kept my half-baked patch mostly up to date with main, and used 
this branch to debug tricky makefile include issues. There were several tricky 
makefile quirks I needed to come up with to get this to work. I tried several 
prototypes along the way, but they all failed by being too complicated, or not 
just "feeling" good to use. This is, I believe, as good as it can possibly get, 
given the limitations inherent in Make. I'm happy to answer questions or 
provide rationale for any specific parts of the implementation.

To facilitate reviewing, I have split this PR into two separate commits, which 
is basically "the tricky parts" and "the trivial parts". The first commit 
introduces the new framework, and makes necessary changes to be able to employ 
it. The second commit goes through each and every makefile, and updates them to 
use the new framework (and to adhere to the style standard).

-------------

Commit messages:
 - Apply framework changes to makefiles
 - Create new framework for logging flow

Changes: https://git.openjdk.org/jdk/pull/23399/files
  Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=23399&range=00
  Issue: https://bugs.openjdk.org/browse/JDK-8348190
  Stats: 2702 lines in 273 files changed: 1647 ins; 485 del; 570 mod
  Patch: https://git.openjdk.org/jdk/pull/23399.diff
  Fetch: git fetch https://git.openjdk.org/jdk.git pull/23399/head:pull/23399

PR: https://git.openjdk.org/jdk/pull/23399

Reply via email to