-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[Dependency Scanner] Add a scanner for explicit placeholder module dependencies #33032
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
Conversation
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.
The change makes sense to me. Can we rename external dependencies to placeholder dependencies? Because what makes these modules different is that they are not ready when the scanning happens.
Yeah, I think placeholder is a better name. |
case .swift(let name): return name | ||
case .clang(let name): return name | ||
case .swift(let name): return name | ||
case .swiftExternal(let name): return name |
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.
Another question: why does the client side need to know whether a module is a placeholder dependency? can we blend them in other module dependencies in the JSON output?
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.
I wrestled with doing this a little bit, here is my rationale for making it a distinct dependency kind:
Using swift-driver
as an example, when the scanner produces a dependency graph for the swift-driver
, it is not enough to have the placeholder just be another swift module in it. One of the things the client will also need (and will be supplied by SwiftPM in this case), is a full dependency graph of the placeholder itself, to get its transitive dependencies and to unique all such transitive dependencies with the modules already in the dependency graph of the main module. Therefore, once the scanner produces this graph, the client will go through all placeholders and substitute their leaf nodes in this graph with a full dependency tree, replacing placeholders with "actual" dependencies.
It made sense to model such nodes as a distinct kind of entity in the graph instead of relying on the client searching for placeholders by-name, but I am curious what you think.
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.
go through all placeholders and substitute their leaf nodes in this graph with a full dependency tree
If we need to transform the graph any way, can we just scan at the point when actual dependencies are ready? avoiding placeholder dependencies altogether?
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.
This particular aspect of this design comes from the way SwiftPM (and I suspect other build systems?) interact with the compiler/driver. SwiftPM forms a build manifest for LLBuild ahead of time, for all targets; instead of planning & building a specific target, then requesting a build plan/manifest for the next target, etc. So this approach is meant to fit with that model. Hence, the driver needs to plan a build for a target/module when its dependencies have not yet been built.
I am also not sure how we would handle transitive dependencies in that case. If we have a target that is a dependency that has been pre-built, I think we would still need its dependency graph to get transitive dependency modules?
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.
An important point to keeping SwiftPM's design w.r.t. planning a full package manifest ahead of time for all targets maximizes the parallelism we can extract from the full package build graph. Building/planning targets one-by-one would limit this, to a degree.
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.
It makes a lot of sense now. Thank you, Artem! Could you document this in the source code explaining the post-processing steps clients will do for these placeholder dependencies and why they are necessary?
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.
Will do!
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.
btw, the post-processing steps make the term placeholder more proper :)
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.
btw, the post-processing steps make the term placeholder more proper :)
It also lends to nicer APIs in the client, resolvePlaceholders
is a very natural-sounding operation.
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.
We actually don't need the synthesized module path for these placeholders, right? we could use some internal ID to facilitate find and replacement. But it's minor though.
09070b1
to
aec6ac0
Compare
@swift-ci please test |
aec6ac0
to
4b2a44f
Compare
@swift-ci please test |
Build failed |
Build failed |
@swift-ci please test OS X Platform |
@swift-ci please smoke test |
@swift-ci please test Windows Platform |
Build failed |
4b2a44f
to
483fafa
Compare
@swift-ci please test |
Build failed |
Build failed |
With: `-external-dependency-module-map-file`
483fafa
to
41f01fa
Compare
@swift-ci please test |
Build failed |
Build failed |
41f01fa
to
6cf9d89
Compare
@swift-ci please test Linux platform |
Build failed |
6cf9d89
to
8fc01c1
Compare
@swift-ci please test Linux platform |
@swift-ci please test OS X platform |
Build failed |
Build failed |
8fc01c1
to
965ca69
Compare
@swift-ci please test |
Build failed |
@swift-ci please test Windows platform |
Build failed |
@swift-ci please test Windows platform |
This PR adds support for the dependency scanner to accept a set of modules that are treated as placeholder dependencies.
Placeholder dependencies are swift modules that the scanner will not be able to locate in its search paths and which are the responsibility of the scanner's client to ensure are provided. Today, encountering an
import
of a module that cannot be discovered in a search path is a failure.The motivation for this change comes from building SwiftPM packages with explicit module builds. Building a SwiftPM package with multiple inter-dependent targets requires that each target’s build job must have its target dependencies’ modules passed into it as explicit module dependencies. Because the build planning stage occurs before any of the targets have been built, each target's module scanning action cannot be made aware of other targets. To support this, SwiftPM must explicitly pass down target dependencies to each target's build planning action (by the driver), which will forward said dependencies to the scanner. Upon encountering an
import
statement of a module known to be a placeholder dependency, instead of searching for the module and discovering its dependencies, the scanner will discover it in an explicit placeholder-dependency-module-map JSON file and note its presence and reflect it accordingly in the resulting dependency graph.This PR:
-placeholder-dependency-module-map-file
that accepts a module map of placeholder module dependencies of the same format as-explicit-swift-module-map-file
.explicit-swift-module-map
code andplaceholder-dependency-module-map
code.ModuleDependencyKind
case:.swiftPlaceholder
) to model placeholder module dependencies.PlaceholderSwiftModuleStubScanner
used by the dependency scanning action to discover this new kind of dependencies.