Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Consume CoarsenedTargets (added in #12251) in javac for cycle resolution, including cycles created by subtargets. #12231
Consume CoarsenedTargets (added in #12251) in javac for cycle resolution, including cycles created by subtargets. #12231
Changes from all commits
ea0ca37
cc4e6a0
File filter
Filter by extension
Conversations
Jump to
There are no files selected for viewing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm. I don't think that this should be necessary.
How I had expected that this would work was that if you received a compilation request for a base target (i.e., one with no sources), then you would coarsen it and recursively request compilation of its dependencies, which would be the expanded/file level targets... which would actually have sources (and so on).
Currently it looks like you're bailing early if a target has no sources, but I would expect the recursion to continue: if you're compiling recursively, some nodes in the recursion not having sources shouldn't short-circuit the recursion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can see how the graph ends up being complete in the unit tests: the
CoarsenedTargets
for the base targets (dep, t1, and t2) depend on their own files.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I had a fair amount of trouble deciding on an overall mental model here. Consuming a
CoarsenedTarget
inCompileJavaSourceRequest
was where I landed. I also waffled for quite a while on spliting this into two rules: one for dealing with expanding and coarsening targets, and one lower level rule for actually running the compilation against a set ofJavaSources
fields.I'm open to changing this, but let me explain my thought process:
The whole crux of the problem with
javac
is limiting my dependency classpath to only the current compilation unit's direct dependencies. We don't want the full transitive closure on the classpath of the current compilation unit, by design, even if we might indirectly, recursively build it in order to build our direct dependencies. So we're really distinguishing here between our compile-time (direct dep) classpath, and a "runtime" classpath that is likely the closure's classpath. This is why the recursion eagerly terminates when it concludes that the current component doesn't produce any classpath entries: we don't need to build it, which means we don't need its deps (only used to build it), which means we don't recursively compile its deps.But by direct dependency, we really mean direct source dependency, or possibly some other kind of resource dependency that can somehow contribute to the classpath but isn't yet modeled. This is where things get sticky, because target expansion sort of changes the definition of "direct" dependency.
That test only uses explicit file dependencies; it doesn't cover the case I'm covering here where, e.g.
t1
depends ondep
instead ofdep.txt:dep
.An example:
A.java
->B
-- (expands to) --> (B.java
andB2.java
).If we use target expansion, we'll automatically get
A.java
->B.java
;A.java
->C.java
; andB.java
<-->C.java
. So subtarget expansion ends up getting us our natural notion of direct dependencies. Just coarseningB
will not do this; we need to do both. Seejavac_test.py:test_compile_with_transitive_multiple_sources
in this PR for a concrete example of this.Stepping way back: my mental model here was to operate over the nodes of an induced coarsened, expanded graph. Then each rule invocation maps 1:1 with a coarsened, expanded component, and its only job is to make sure that its recursive calls are also over coarsened, expanded components. Expanding gets us the right notion of direct dependencies in the presence of subtarget expansion, while coarsening gets us the right notion of a single compilation unit in the presence of source-target cycles.
I'm pretty confident this needs a more generic model, since we're going to need to eventually worry about other rules that can contribute to the compilation classpath, which means we're probably going to need to request a union product from our dependencies. That's where I was imagining two layers of rules, where
compile_java_source
is lower level and not expected to think hard about how to expand its dependencies. But without another example of a rule that produces files for the compilation classpath, I worry that attempting to model that is premature. So I opted for the "direct" route here just to getjavac
working and exercising the existing coarsening/expansion machinery.Again, I'm happy to change this if you have an idea of how to remodel it, but pay particular attention to the example in
javac_test.py:test_compile_with_transitive_multiple_sources
to make sure that that case is covered (or why that case is somehow not actually a valid graph to test against).