Skip to content

[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

Merged
merged 8 commits into from
Jul 28, 2020

Conversation

artemcm
Copy link
Contributor

@artemcm artemcm commented Jul 21, 2020

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:

  • Adds an option: -placeholder-dependency-module-map-file that accepts a module map of placeholder module dependencies of the same format as -explicit-swift-module-map-file.
  • Refactors parsing of the module map JSON files into a standalone utility used by explicit-swift-module-map code and placeholder-dependency-module-map code.
  • Adds a new dependency kind (ModuleDependencyKind case: .swiftPlaceholder) to model placeholder module dependencies.
  • Adds PlaceholderSwiftModuleStubScanner used by the dependency scanning action to discover this new kind of dependencies.

@artemcm artemcm requested review from DougGregor and nkcsgexi July 21, 2020 19:19
Copy link
Contributor

@nkcsgexi nkcsgexi left a 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.

@artemcm
Copy link
Contributor Author

artemcm commented Jul 21, 2020

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
Copy link
Contributor

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?

Copy link
Contributor Author

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.

Copy link
Contributor

@nkcsgexi nkcsgexi Jul 21, 2020

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?

Copy link
Contributor Author

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?

Copy link
Contributor Author

@artemcm artemcm Jul 21, 2020

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.

Copy link
Contributor

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do!

Copy link
Contributor

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 :)

Copy link
Contributor Author

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.

Copy link
Contributor

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.

@artemcm artemcm changed the title [Dependency Scanner] Add a scanner for explicit external module dependencies [Dependency Scanner] Add a scanner for explicit placeholder module dependencies Jul 21, 2020
@artemcm artemcm force-pushed the ExplicitPackageBuilds branch 3 times, most recently from 09070b1 to aec6ac0 Compare July 22, 2020 20:52
@artemcm
Copy link
Contributor Author

artemcm commented Jul 23, 2020

@swift-ci please test

@artemcm
Copy link
Contributor Author

artemcm commented Jul 23, 2020

@swift-ci please test

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - aec6ac0a1e9250483c6f4aa5480fd583a2d82df2

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - aec6ac0a1e9250483c6f4aa5480fd583a2d82df2

@artemcm
Copy link
Contributor Author

artemcm commented Jul 23, 2020

@swift-ci please test OS X Platform

@artemcm
Copy link
Contributor Author

artemcm commented Jul 23, 2020

@swift-ci please smoke test

@artemcm
Copy link
Contributor Author

artemcm commented Jul 23, 2020

@swift-ci please test Windows Platform

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - 4b2a44f231a084a938483cebc541595fcb00567c

@artemcm
Copy link
Contributor Author

artemcm commented Jul 24, 2020

@swift-ci please test

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 4b2a44f231a084a938483cebc541595fcb00567c

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - 4b2a44f231a084a938483cebc541595fcb00567c

@artemcm artemcm force-pushed the ExplicitPackageBuilds branch from 483fafa to 41f01fa Compare July 27, 2020 18:28
@artemcm
Copy link
Contributor Author

artemcm commented Jul 27, 2020

@swift-ci please test

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 483fafa86e371d1365f0fcb2d198e603df4abba5

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - 483fafa86e371d1365f0fcb2d198e603df4abba5

@artemcm artemcm force-pushed the ExplicitPackageBuilds branch from 41f01fa to 6cf9d89 Compare July 28, 2020 01:48
@artemcm
Copy link
Contributor Author

artemcm commented Jul 28, 2020

@swift-ci please test Linux platform

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 6cf9d898e335f033c7591833c666423345a9e2a3

@artemcm artemcm force-pushed the ExplicitPackageBuilds branch from 6cf9d89 to 8fc01c1 Compare July 28, 2020 04:30
@artemcm
Copy link
Contributor Author

artemcm commented Jul 28, 2020

@swift-ci please test Linux platform

@artemcm
Copy link
Contributor Author

artemcm commented Jul 28, 2020

@swift-ci please test OS X platform

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 6cf9d898e335f033c7591833c666423345a9e2a3

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - 6cf9d898e335f033c7591833c666423345a9e2a3

@artemcm artemcm force-pushed the ExplicitPackageBuilds branch from 8fc01c1 to 965ca69 Compare July 28, 2020 18:34
@artemcm
Copy link
Contributor Author

artemcm commented Jul 28, 2020

@swift-ci please test

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 8fc01c1804f3aa4f9f373d4e45da43e040dfaeb1

@artemcm
Copy link
Contributor Author

artemcm commented Jul 28, 2020

@swift-ci please test Windows platform

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - 8fc01c1804f3aa4f9f373d4e45da43e040dfaeb1

@artemcm
Copy link
Contributor Author

artemcm commented Jul 28, 2020

@swift-ci please test Windows platform

@artemcm artemcm merged commit 413bbab into swiftlang:master Jul 28, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants