@@ -100,7 +100,11 @@ public actor SwiftPMBuildSystem {
100
100
101
101
var fileToTarget : [ AbsolutePath : SwiftBuildTarget ] = [ : ]
102
102
var sourceDirToTarget : [ AbsolutePath : SwiftBuildTarget ] = [ : ]
103
- var targets : [ SwiftBuildTarget ] = [ ]
103
+
104
+ /// Maps target ids (aka. `ConfiguredTarget.targetID`) to their SwiftPM build target as well as an index in their
105
+ /// topological sorting. Targets with lower index are more low level, ie. targets with higher indices depend on
106
+ /// targets with lower indices.
107
+ var targets : [ String : ( index: Int , buildTarget: SwiftBuildTarget ) ] = [ : ]
104
108
105
109
/// The URIs for which the delegate has registered for change notifications,
106
110
/// mapped to the language the delegate specified when registering for change notifications.
@@ -119,6 +123,11 @@ public actor SwiftPMBuildSystem {
119
123
/// Force-unwrapped optional because initializing it requires access to `self`.
120
124
var fileDependenciesUpdatedDebouncer : Debouncer < Set < DocumentURI > > ! = nil
121
125
126
+ /// A `ObservabilitySystem` from `SwiftPM` that logs.
127
+ private let observabilitySystem = ObservabilitySystem ( { scope, diagnostic in
128
+ logger. log ( level: diagnostic. severity. asLogLevel, " SwiftPM log: \( diagnostic. description) " )
129
+ } )
130
+
122
131
/// Creates a build system using the Swift Package Manager, if this workspace is a package.
123
132
///
124
133
/// - Parameters:
@@ -238,9 +247,6 @@ public actor SwiftPMBuildSystem {
238
247
239
248
extension SwiftPMBuildSystem {
240
249
public func generateBuildGraph( ) async throws {
241
- let observabilitySystem = ObservabilitySystem ( { scope, diagnostic in
242
- logger. log ( level: diagnostic. severity. asLogLevel, " SwiftPM log: \( diagnostic. description) " )
243
- } )
244
250
try self . workspace. resolve (
245
251
root: PackageGraphRootInput ( packages: [ AbsolutePath ( projectRoot) ] ) ,
246
252
observabilityScope: observabilitySystem. topScope
@@ -258,10 +264,6 @@ extension SwiftPMBuildSystem {
258
264
}
259
265
}
260
266
261
- let observabilitySystem = ObservabilitySystem ( { scope, diagnostic in
262
- logger. log ( level: diagnostic. severity. asLogLevel, " SwiftPM log: \( diagnostic. description) " )
263
- } )
264
-
265
267
let modulesGraph = try self . workspace. loadPackageGraph (
266
268
rootInput: PackageGraphRootInput ( packages: [ AbsolutePath ( projectRoot) ] ) ,
267
269
forceResolvedVersions: true ,
@@ -282,7 +284,15 @@ extension SwiftPMBuildSystem {
282
284
/// with only some properties modified.
283
285
self . modulesGraph = modulesGraph
284
286
285
- self . targets = try buildDescription. allTargetsInTopologicalOrder ( in: modulesGraph)
287
+ self . targets = Dictionary (
288
+ try buildDescription. allTargetsInTopologicalOrder ( in: modulesGraph) . enumerated ( ) . map { ( index, target) in
289
+ return ( key: target. name, ( index, target) )
290
+ } ,
291
+ uniquingKeysWith: { first, second in
292
+ logger. fault ( " Found two targets with the same name \( first. buildTarget. name) " )
293
+ return second
294
+ }
295
+ )
286
296
287
297
self . fileToTarget = [ AbsolutePath: SwiftBuildTarget] (
288
298
modulesGraph. allTargets. flatMap { target in
@@ -353,14 +363,8 @@ extension SwiftPMBuildSystem: SKCore.BuildSystem {
353
363
return try settings ( forPackageManifest: path)
354
364
}
355
365
356
- let buildTargets = self . targets. filter ( { $0. name == configuredTarget. targetID } )
357
- if buildTargets. count > 1 {
358
- logger. error ( " Found multiple targets with name \( configuredTarget. targetID) . Picking the first one " )
359
- }
360
- guard let buildTarget = buildTargets. first else {
361
- if buildTargets. isEmpty {
362
- logger. error ( " Did not find target with name \( configuredTarget. targetID) " )
363
- }
366
+ guard let buildTarget = self . targets [ configuredTarget. targetID] ? . buildTarget else {
367
+ logger. error ( " Did not find target with name \( configuredTarget. targetID) " )
364
368
return nil
365
369
}
366
370
@@ -408,8 +412,8 @@ extension SwiftPMBuildSystem: SKCore.BuildSystem {
408
412
409
413
public func topologicalSort( of targets: [ ConfiguredTarget ] ) -> [ ConfiguredTarget ] ? {
410
414
return targets. sorted { ( lhs: ConfiguredTarget , rhs: ConfiguredTarget ) -> Bool in
411
- let lhsIndex = self . targets. firstIndex ( where : { $0 . name == lhs. targetID } ) ?? self . targets. count
412
- let rhsIndex = self . targets. firstIndex ( where : { $0 . name == rhs . targetID } ) ?? self . targets. count
415
+ let lhsIndex = self . targets [ lhs. targetID] ? . index ?? self . targets. count
416
+ let rhsIndex = self . targets [ lhs . targetID] ? . index ?? self . targets. count
413
417
return lhsIndex < rhsIndex
414
418
}
415
419
}
@@ -443,7 +447,7 @@ extension SwiftPMBuildSystem: SKCore.BuildSystem {
443
447
]
444
448
let process = Process (
445
449
arguments: arguments,
446
- workingDirectory: try TSCBasic . AbsolutePath ( validating : workspacePath. pathString )
450
+ workingDirectory: workspacePath
447
451
)
448
452
try process. launch ( )
449
453
let result = try await process. waitUntilExitSendingSigIntOnTaskCancellation ( )
@@ -456,7 +460,7 @@ extension SwiftPMBuildSystem: SKCore.BuildSystem {
456
460
let stderr = ( try ? String ( bytes: result. stderrOutput. get ( ) , encoding: . utf8) ) ?? " <no stderr> "
457
461
logger. debug (
458
462
"""
459
- Preparation of targets \( target. targetID) terminated with non-zero exit code \( code)
463
+ Preparation of target \( target. targetID) terminated with non-zero exit code \( code)
460
464
Stderr:
461
465
\( stderr)
462
466
Stdout:
@@ -468,11 +472,11 @@ extension SwiftPMBuildSystem: SKCore.BuildSystem {
468
472
// The indexing job finished with a signal. Could be because the compiler crashed.
469
473
// Ignore signal exit codes if this task has been cancelled because the compiler exits with SIGINT if it gets
470
474
// interrupted.
471
- logger. error ( " Preparation of targets \( target. targetID) signaled \( signal) " )
475
+ logger. error ( " Preparation of target \( target. targetID) signaled \( signal) " )
472
476
}
473
477
case . abnormal( exception: let exception) :
474
478
if !Task. isCancelled {
475
- logger. error ( " Preparation of targets \( target. targetID) exited abnormally \( exception) " )
479
+ logger. error ( " Preparation of target \( target. targetID) exited abnormally \( exception) " )
476
480
}
477
481
}
478
482
}
0 commit comments