Skip to content

Commit 659199f

Browse files
committed
[Build] NFC: Start using ModuleBuildDescription.{recursive}Dependencies
1 parent f330f94 commit 659199f

File tree

4 files changed

+83
-70
lines changed

4 files changed

+83
-70
lines changed

Sources/Build/BuildManifest/LLBuildManifestBuilder+Clang.swift

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,30 +32,36 @@ extension LLBuildManifestBuilder {
3232
inputs.append(resourcesNode)
3333
}
3434

35-
func addStaticTargetInputs(_ target: ResolvedModule) {
36-
if case .swift(let desc)? = self.plan.targetMap[target.id], target.type == .library {
35+
func addStaticTargetInputs(_ description: ModuleBuildDescription?) {
36+
if case .swift(let desc) = description, desc.target.type == .library {
3737
inputs.append(file: desc.moduleOutputPath)
3838
}
3939
}
4040

41-
for dependency in target.target.dependencies(satisfying: target.buildEnvironment) {
41+
for dependency in target.dependencies(using: self.plan) {
4242
switch dependency {
43-
case .module(let target, _):
44-
addStaticTargetInputs(target)
43+
case .module(_, let description):
44+
addStaticTargetInputs(description)
4545

46-
case .product(let product, _):
46+
case .product(let product, let productDescription):
4747
switch product.type {
4848
case .executable, .snippet, .library(.dynamic), .macro:
49-
guard let planProduct = plan.productMap[product.id] else {
50-
throw InternalError("unknown product \(product)")
49+
guard let productDescription else {
50+
throw InternalError("No build description for product: \(product)")
5151
}
5252
// Establish a dependency on binary of the product.
53-
let binary = try planProduct.binaryPath
54-
inputs.append(file: binary)
53+
try inputs.append(file: productDescription.binaryPath)
5554

5655
case .library(.automatic), .library(.static), .plugin:
57-
for target in product.modules {
58-
addStaticTargetInputs(target)
56+
for module in product.modules {
57+
guard let dependencyDescription = self.plan.description(
58+
for: module,
59+
context: product.type == .plugin ? .host : target.destination
60+
) else
61+
{
62+
throw InternalError("unknown module: \(module)")
63+
}
64+
addStaticTargetInputs(dependencyDescription)
5965
}
6066
case .test:
6167
break

Sources/Build/BuildManifest/LLBuildManifestBuilder+Swift.swift

Lines changed: 59 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -191,10 +191,8 @@ extension LLBuildManifestBuilder {
191191
public func addTargetsToExplicitBuildManifest() throws {
192192
// Sort the product targets in topological order in order to collect and "bubble up"
193193
// their respective dependency graphs to the depending targets.
194-
let nodes = self.plan.targets.compactMap {
195-
ResolvedModule.Dependency.module($0.module, conditions: [])
196-
}
197-
let allPackageDependencies = try topologicalSort(nodes, successors: { $0.dependencies })
194+
let allPackageDependencies = self.plan.targets.flatMap { $0.recursiveDependencies(using: self.plan) }
195+
198196
// Instantiate the inter-module dependency oracle which will cache commonly-scanned
199197
// modules across targets' Driver instances.
200198
let dependencyOracle = InterModuleDependencyOracle()
@@ -206,14 +204,15 @@ extension LLBuildManifestBuilder {
206204

207205
// Create commands for all module descriptions in the plan.
208206
for dependency in allPackageDependencies.reversed() {
209-
guard case .module(let target, _) = dependency else {
207+
guard case .module(let module, let description) = dependency else {
210208
// Product dependency build jobs are added after the fact.
211209
// Targets that depend on product dependencies will expand the corresponding
212210
// product into its constituent targets.
213211
continue
214212
}
215-
guard target.underlying.type != .systemModule,
216-
target.underlying.type != .binary
213+
214+
guard module.underlying.type != .systemModule,
215+
module.underlying.type != .binary
217216
else {
218217
// Much like non-Swift targets, system modules will consist of a modulemap
219218
// somewhere in the filesystem, with the path to that module being either
@@ -225,9 +224,11 @@ extension LLBuildManifestBuilder {
225224
// be able to detect such targets' modules.
226225
continue
227226
}
228-
guard let description = plan.targetMap[target.id] else {
229-
throw InternalError("Expected description for target \(target)")
227+
228+
guard let description else {
229+
throw InternalError("Expected description for module \(module)")
230230
}
231+
231232
switch description {
232233
case .swift(let desc):
233234
try self.createExplicitSwiftTargetCompileCommand(
@@ -319,32 +320,29 @@ extension LLBuildManifestBuilder {
319320
for targetDescription: ModuleBuildDescription,
320321
dependencyModuleDetailsMap: inout SwiftDriver.ExternalTargetModuleDetailsMap
321322
) throws {
322-
for dependency in targetDescription.module.dependencies(satisfying: targetDescription.buildParameters.buildEnvironment) {
323+
for dependency in targetDescription.dependencies(using: self.plan) {
323324
switch dependency {
324-
case .product:
325-
// Product dependencies are broken down into the targets that make them up.
326-
guard let dependencyProduct = dependency.product else {
327-
throw InternalError("unknown dependency product for \(dependency)")
328-
}
329-
for dependencyProductTarget in dependencyProduct.modules {
330-
guard let dependencyTargetDescription = self.plan.targetMap[dependencyProductTarget.id] else {
331-
throw InternalError("unknown dependency target for \(dependencyProductTarget)")
325+
case .product(let product, let productDescription):
326+
for productDependency in product.modules {
327+
guard let dependencyModuleDescription = self.plan.description(
328+
for: productDependency,
329+
context: productDescription?.destination ?? targetDescription.destination
330+
) else
331+
{
332+
throw InternalError("unknown dependency target for \(productDependency)")
332333
}
333334
try self.addTargetDependencyInfo(
334-
for: dependencyTargetDescription,
335+
for: dependencyModuleDescription,
335336
dependencyModuleDetailsMap: &dependencyModuleDetailsMap
336337
)
337338
}
338-
case .module:
339-
// Product dependencies are broken down into the targets that make them up.
340-
guard
341-
let dependencyTarget = dependency.module,
342-
let dependencyTargetDescription = self.plan.targetMap[dependencyTarget.id]
343-
else {
344-
throw InternalError("unknown dependency target for \(dependency)")
339+
case .module(let dependencyModule, let dependencyDescription):
340+
guard let dependencyDescription else {
341+
throw InternalError("No build description for module: \(dependencyModule)")
345342
}
343+
// Product dependencies are broken down into the targets that make them up.
346344
try self.addTargetDependencyInfo(
347-
for: dependencyTargetDescription,
345+
for: dependencyDescription,
348346
dependencyModuleDetailsMap: &dependencyModuleDetailsMap
349347
)
350348
}
@@ -422,63 +420,73 @@ extension LLBuildManifestBuilder {
422420

423421
let prepareForIndexing = target.buildParameters.prepareForIndexing
424422

425-
func addStaticTargetInputs(_ target: ResolvedModule) throws {
423+
func addStaticTargetInputs(_ module: ResolvedModule, _ description: ModuleBuildDescription?) throws {
426424
// Ignore C Modules.
427-
if target.underlying is SystemLibraryModule { return }
425+
if module.underlying is SystemLibraryModule { return }
428426
// Ignore Binary Modules.
429-
if target.underlying is BinaryModule { return }
427+
if module.underlying is BinaryModule { return }
430428
// Ignore Plugin Modules.
431-
if target.underlying is PluginModule { return }
429+
if module.underlying is PluginModule { return }
430+
431+
guard let description else {
432+
throw InternalError("No build description for module: \(module)")
433+
}
432434

433435
// Depend on the binary for executable targets.
434-
if target.type == .executable && prepareForIndexing == .off {
435-
// FIXME: Optimize.
436+
if module.type == .executable && prepareForIndexing == .off {
437+
// FIXME: Optimize. Build plan could build a mapping between executable modules
438+
// and their products to speed up search here, which is inefficient if the plan
439+
// contains a lot of products.
436440
if let productDescription = try plan.productMap.values.first(where: {
437-
try $0.product.type == .executable && $0.product.executableModule.id == target.id
441+
try $0.product.type == .executable &&
442+
$0.product.executableModule.id == module.id &&
443+
$0.destination == description.destination
438444
}) {
439445
try inputs.append(file: productDescription.binaryPath)
440446
}
441447
return
442448
}
443449

444-
switch self.plan.targetMap[target.id] {
445-
case .swift(let target)?:
446-
inputs.append(file: target.moduleOutputPath)
447-
case .clang(let target)?:
450+
switch description {
451+
case .swift(let swiftDescription):
452+
inputs.append(file: swiftDescription.moduleOutputPath)
453+
case .clang(let clangDescription):
448454
if prepareForIndexing != .off {
449455
// In preparation, we're only building swiftmodules
450456
// propagate the dependency to the header files in this target
451-
for header in target.clangTarget.headers {
457+
for header in clangDescription.clangTarget.headers {
452458
inputs.append(file: header)
453459
}
454460
} else {
455-
for object in try target.objects {
461+
for object in try clangDescription.objects {
456462
inputs.append(file: object)
457463
}
458464
}
459-
case nil:
460-
throw InternalError("unexpected: target \(target) not in target map \(self.plan.targetMap)")
461465
}
462466
}
463467

464-
for dependency in target.target.dependencies(satisfying: target.buildParameters.buildEnvironment) {
468+
for dependency in target.dependencies(using: self.plan) {
465469
switch dependency {
466-
case .module(let target, _):
467-
try addStaticTargetInputs(target)
470+
case .module(let module, let description):
471+
try addStaticTargetInputs(module, description)
468472

469-
case .product(let product, _):
473+
case .product(let product, let productDescription):
470474
switch product.type {
471475
case .executable, .snippet, .library(.dynamic), .macro:
472-
guard let planProduct = plan.productMap[product.id] else {
473-
throw InternalError("unknown product \(product)")
476+
guard let productDescription else {
477+
throw InternalError("No description for product: \(product)")
474478
}
475479
// Establish a dependency on binary of the product.
476-
try inputs.append(file: planProduct.binaryPath)
480+
try inputs.append(file: productDescription.binaryPath)
477481

478482
// For automatic and static libraries, and plugins, add their targets as static input.
479483
case .library(.automatic), .library(.static), .plugin:
480-
for target in product.modules {
481-
try addStaticTargetInputs(target)
484+
for module in product.modules {
485+
let description = self.plan.description(
486+
for: module,
487+
context: product.type == .plugin ? .host : target.destination
488+
)
489+
try addStaticTargetInputs(module, description)
482490
}
483491

484492
case .test:

Sources/Build/BuildPlan/BuildPlan+Clang.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ import class PackageModel.SystemLibraryModule
1818
extension BuildPlan {
1919
/// Plan a Clang target.
2020
func plan(clangTarget: ClangModuleBuildDescription) throws {
21-
let dependencies = try clangTarget.target.recursiveDependencies(satisfying: clangTarget.buildEnvironment)
21+
let dependencies = clangTarget.recursiveDependencies(using: self)
2222

23-
for case .module(let dependency, _) in dependencies {
23+
for case .module(let dependency, let description) in dependencies {
2424
switch dependency.underlying {
2525
case is SwiftModule:
26-
if case let .swift(dependencyTargetDescription)? = targetMap[dependency.id] {
26+
if case let .swift(dependencyTargetDescription)? = description {
2727
if let moduleMap = dependencyTargetDescription.moduleMap {
2828
clangTarget.additionalFlags += ["-fmodule-map-file=\(moduleMap.pathString)"]
2929
}
@@ -34,7 +34,7 @@ extension BuildPlan {
3434
clangTarget.additionalFlags += ["-I", target.includeDir.pathString]
3535

3636
// Add the modulemap of the dependency if it has one.
37-
if case let .clang(dependencyTargetDescription)? = targetMap[dependency.id] {
37+
if case let .clang(dependencyTargetDescription)? = description {
3838
if let moduleMap = dependencyTargetDescription.moduleMap {
3939
clangTarget.additionalFlags += ["-fmodule-map-file=\(moduleMap.pathString)"]
4040
}

Sources/Build/BuildPlan/BuildPlan+Swift.swift

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,10 @@ extension BuildPlan {
2020
func plan(swiftTarget: SwiftModuleBuildDescription) throws {
2121
// We need to iterate recursive dependencies because Swift compiler needs to see all the targets a target
2222
// depends on.
23-
let environment = swiftTarget.buildParameters.buildEnvironment
24-
for case .module(let dependency, _) in try swiftTarget.target.recursiveDependencies(satisfying: environment) {
23+
for case .module(let dependency, let description) in swiftTarget.recursiveDependencies(using: self) {
2524
switch dependency.underlying {
2625
case let underlyingTarget as ClangModule where underlyingTarget.type == .library:
27-
guard case let .clang(target)? = targetMap[dependency.id] else {
26+
guard case let .clang(target)? = description else {
2827
throw InternalError("unexpected clang target \(underlyingTarget)")
2928
}
3029
// Add the path to modulemap of the dependency. Currently we require that all Clang targets have a

0 commit comments

Comments
 (0)