Skip to content

Commit 94203e5

Browse files
authored
SwiftBuildSystem: Expose public API for reuse by SourceKit-LSP/BSP (#8842)
Reorganize some of the SwiftBuildSystem code so we can share the implementation of - session creation - writing PIF - build request construction There should be no functional change to SwiftPM
1 parent cd28d1b commit 94203e5

File tree

1 file changed

+91
-74
lines changed

1 file changed

+91
-74
lines changed

Sources/SwiftBuildSupport/SwiftBuildSystem.swift

Lines changed: 91 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -57,44 +57,52 @@ func withService(
5757
await service.close()
5858
}
5959

60-
func withSession(
60+
public func createSession(
6161
service: SWBBuildService,
6262
name: String,
6363
toolchainPath: Basics.AbsolutePath,
64-
packageManagerResourcesDirectory: Basics.AbsolutePath?,
65-
body: @escaping (
66-
_ session: SWBBuildServiceSession,
67-
_ diagnostics: [SwiftBuild.SwiftBuildMessage.DiagnosticInfo]
68-
) async throws -> Void
69-
) async throws {
64+
packageManagerResourcesDirectory: Basics.AbsolutePath?
65+
) async throws-> (SWBBuildServiceSession, [SwiftBuildMessage.DiagnosticInfo]) {
7066
// SWIFT_EXEC and SWIFT_EXEC_MANIFEST may need to be overridden in debug scenarios in order to pick up Open Source toolchains
7167
let sessionResult = if toolchainPath.components.contains(where: { $0.hasSuffix(".xctoolchain") }) {
7268
await service.createSession(name: name, developerPath: nil, resourceSearchPaths: packageManagerResourcesDirectory.map { [$0.pathString] } ?? [], cachePath: nil, inferiorProductsPath: nil, environment: nil)
7369
} else {
7470
await service.createSession(name: name, swiftToolchainPath: toolchainPath.pathString, resourceSearchPaths: packageManagerResourcesDirectory.map { [$0.pathString] } ?? [], cachePath: nil, inferiorProductsPath: nil, environment: nil)
7571
}
76-
7772
switch sessionResult {
7873
case (.success(let session), let diagnostics):
79-
do {
80-
try await body(session, diagnostics)
81-
} catch {
82-
do {
83-
try await session.close()
84-
} catch _ {
85-
// Assumption is that the first error is the most important one
86-
throw SessionFailedError(error: error, diagnostics: diagnostics)
87-
}
88-
89-
throw SessionFailedError(error: error, diagnostics: diagnostics)
90-
}
74+
return (session, diagnostics)
75+
case (.failure(let error), let diagnostics):
76+
throw SessionFailedError(error: error, diagnostics: diagnostics)
77+
}
78+
}
9179

80+
func withSession(
81+
service: SWBBuildService,
82+
name: String,
83+
toolchainPath: Basics.AbsolutePath,
84+
packageManagerResourcesDirectory: Basics.AbsolutePath?,
85+
body: @escaping (
86+
_ session: SWBBuildServiceSession,
87+
_ diagnostics: [SwiftBuild.SwiftBuildMessage.DiagnosticInfo]
88+
) async throws -> Void
89+
) async throws {
90+
let (session, diagnostics) = try await createSession(service: service, name: name, toolchainPath: toolchainPath, packageManagerResourcesDirectory: packageManagerResourcesDirectory)
91+
do {
92+
try await body(session, diagnostics)
93+
} catch let bodyError {
9294
do {
9395
try await session.close()
94-
} catch {
95-
throw SessionFailedError(error: error, diagnostics: diagnostics)
96+
} catch _ {
97+
// Assumption is that the first error is the most important one
98+
throw bodyError
9699
}
97-
case (.failure(let error), let diagnostics):
100+
101+
throw bodyError
102+
}
103+
do {
104+
try await session.close()
105+
} catch {
98106
throw SessionFailedError(error: error, diagnostics: diagnostics)
99107
}
100108
}
@@ -272,13 +280,7 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem {
272280
return
273281
}
274282

275-
let pifBuilder = try await getPIFBuilder()
276-
let pif = try await pifBuilder.generatePIF(
277-
printPIFManifestGraphviz: buildParameters.printPIFManifestGraphviz,
278-
buildParameters: buildParameters,
279-
)
280-
281-
try self.fileSystem.writeIfChanged(path: buildParameters.pifManifest, string: pif)
283+
try await writePIF(buildParameters: buildParameters)
282284

283285
try await startSWBuildOperation(pifTargetName: subset.pifTargetName)
284286
}
@@ -287,8 +289,7 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem {
287289
let buildStartTime = ContinuousClock.Instant.now
288290

289291
try await withService(connectionMode: .inProcessStatic(swiftbuildServiceEntryPoint)) { service in
290-
let parameters = try self.makeBuildParameters()
291-
let derivedDataPath = self.buildParameters.dataPath.pathString
292+
let derivedDataPath = self.buildParameters.dataPath
292293

293294
let progressAnimation = ProgressAnimation.percent(
294295
stream: self.outputStream,
@@ -311,7 +312,7 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem {
311312
}
312313

313314
// Find the targets to build.
314-
let configuredTargets: [SWBConfiguredTarget]
315+
let configuredTargets: [SWBTargetGUID]
315316
do {
316317
let workspaceInfo = try await session.workspaceInfo()
317318

@@ -322,7 +323,7 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem {
322323
self.observabilityScope.emit(error: "Could not find target named '\(targetName)'")
323324
throw Diagnostics.fatalError
324325
case 1:
325-
return SWBConfiguredTarget(guid: infos[0].guid, parameters: parameters)
326+
return SWBTargetGUID(rawValue: infos[0].guid)
326327
default:
327328
self.observabilityScope.emit(error: "Found multiple targets named '\(targetName)'")
328329
throw Diagnostics.fatalError
@@ -333,44 +334,7 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem {
333334
throw error
334335
}
335336

336-
var request = SWBBuildRequest()
337-
request.parameters = parameters
338-
request.configuredTargets = configuredTargets
339-
request.useParallelTargets = true
340-
request.useImplicitDependencies = false
341-
request.useDryRun = false
342-
request.hideShellScriptEnvironment = true
343-
request.showNonLoggedProgress = true
344-
345-
// Override the arena. We need to apply the arena info to both the request-global build
346-
// parameters as well as the target-specific build parameters, since they may have been
347-
// deserialized from the build request file above overwriting the build parameters we set
348-
// up earlier in this method.
349-
350-
#if os(Windows)
351-
let ddPathPrefix = derivedDataPath.replacingOccurrences(of: "\\", with: "/")
352-
#else
353-
let ddPathPrefix = derivedDataPath
354-
#endif
355-
356-
let arenaInfo = SWBArenaInfo(
357-
derivedDataPath: ddPathPrefix,
358-
buildProductsPath: ddPathPrefix + "/Products",
359-
buildIntermediatesPath: ddPathPrefix + "/Intermediates.noindex",
360-
pchPath: ddPathPrefix + "/PCH",
361-
indexRegularBuildProductsPath: nil,
362-
indexRegularBuildIntermediatesPath: nil,
363-
indexPCHPath: ddPathPrefix,
364-
indexDataStoreFolderPath: ddPathPrefix,
365-
indexEnableDataStore: request.parameters.arenaInfo?.indexEnableDataStore ?? false
366-
)
367-
368-
request.parameters.arenaInfo = arenaInfo
369-
request.configuredTargets = request.configuredTargets.map { configuredTarget in
370-
var configuredTarget = configuredTarget
371-
configuredTarget.parameters?.arenaInfo = arenaInfo
372-
return configuredTarget
373-
}
337+
let request = try self.makeBuildRequest(configuredTargets: configuredTargets, derivedDataPath: derivedDataPath)
374338

375339
struct BuildState {
376340
private var activeTasks: [Int: SwiftBuild.SwiftBuildMessage.TaskStartedInfo] = [:]
@@ -495,7 +459,7 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem {
495459
}
496460
}
497461

498-
func makeRunDestination() -> SwiftBuild.SWBRunDestinationInfo {
462+
private func makeRunDestination() -> SwiftBuild.SWBRunDestinationInfo {
499463
let platformName: String
500464
let sdkName: String
501465
if self.buildParameters.triple.isAndroid() {
@@ -528,7 +492,7 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem {
528492
)
529493
}
530494

531-
func makeBuildParameters() throws -> SwiftBuild.SWBBuildParameters {
495+
private func makeBuildParameters() throws -> SwiftBuild.SWBBuildParameters {
532496
// Generate the run destination parameters.
533497
let runDestination = makeRunDestination()
534498

@@ -609,6 +573,49 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem {
609573
return params
610574
}
611575

576+
public func makeBuildRequest(configuredTargets: [SWBTargetGUID], derivedDataPath: Basics.AbsolutePath) throws -> SWBBuildRequest {
577+
var request = SWBBuildRequest()
578+
request.parameters = try makeBuildParameters()
579+
request.configuredTargets = configuredTargets.map { SWBConfiguredTarget(guid: $0.rawValue, parameters: request.parameters) }
580+
request.useParallelTargets = true
581+
request.useImplicitDependencies = false
582+
request.useDryRun = false
583+
request.hideShellScriptEnvironment = true
584+
request.showNonLoggedProgress = true
585+
586+
// Override the arena. We need to apply the arena info to both the request-global build
587+
// parameters as well as the target-specific build parameters, since they may have been
588+
// deserialized from the build request file above overwriting the build parameters we set
589+
// up earlier in this method.
590+
591+
#if os(Windows)
592+
let ddPathPrefix = derivedDataPath.pathString.replacingOccurrences(of: "\\", with: "/")
593+
#else
594+
let ddPathPrefix = derivedDataPath.pathString
595+
#endif
596+
597+
let arenaInfo = SWBArenaInfo(
598+
derivedDataPath: ddPathPrefix,
599+
buildProductsPath: ddPathPrefix + "/Products",
600+
buildIntermediatesPath: ddPathPrefix + "/Intermediates.noindex",
601+
pchPath: ddPathPrefix + "/PCH",
602+
indexRegularBuildProductsPath: nil,
603+
indexRegularBuildIntermediatesPath: nil,
604+
indexPCHPath: ddPathPrefix,
605+
indexDataStoreFolderPath: ddPathPrefix,
606+
indexEnableDataStore: request.parameters.arenaInfo?.indexEnableDataStore ?? false
607+
)
608+
609+
request.parameters.arenaInfo = arenaInfo
610+
request.configuredTargets = request.configuredTargets.map { configuredTarget in
611+
var configuredTarget = configuredTarget
612+
configuredTarget.parameters?.arenaInfo = arenaInfo
613+
return configuredTarget
614+
}
615+
616+
return request
617+
}
618+
612619
private static func constructDebuggingSettingsOverrides(from parameters: BuildParameters.Debugging) -> [String: String] {
613620
var settings: [String: String] = [:]
614621
// TODO: debugInfoFormat: https://github.com/swiftlang/swift-build/issues/560
@@ -700,6 +707,16 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem {
700707
}
701708
}
702709

710+
public func writePIF(buildParameters: BuildParameters) async throws {
711+
let pifBuilder = try await getPIFBuilder()
712+
let pif = try await pifBuilder.generatePIF(
713+
printPIFManifestGraphviz: buildParameters.printPIFManifestGraphviz,
714+
buildParameters: buildParameters,
715+
)
716+
717+
try self.fileSystem.writeIfChanged(path: buildParameters.pifManifest, string: pif)
718+
}
719+
703720
public func cancel(deadline: DispatchTime) throws {}
704721

705722
/// Returns the package graph using the graph loader closure.

0 commit comments

Comments
 (0)