Skip to content

Commit 017c710

Browse files
authored
Merge pull request #2010 from ahoppen/6.1/retry-build-description-load
[6.1] Retry loading the build description if it fails to write `output-file-map.json` on Windows
2 parents 02ee070 + faa2232 commit 017c710

File tree

1 file changed

+47
-11
lines changed

1 file changed

+47
-11
lines changed

Sources/BuildSystemIntegration/SwiftPMBuildSystem.swift

+47-11
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,52 @@ package actor SwiftPMBuildSystem: BuiltInBuildSystem {
341341
}
342342
}
343343

344+
/// Loading the build description sometimes fails non-deterministically on Windows because it's unable to write
345+
/// `output-file-map.json`, probably due to https://github.com/swiftlang/swift-package-manager/issues/8038.
346+
/// If this happens, retry loading the build description up to `maxLoadAttempt` times.
347+
private func loadBuildDescriptionWithRetryOnOutputFileMapWriteErrorOnWindows(
348+
modulesGraph: ModulesGraph,
349+
maxLoadAttempts: Int = 5
350+
) async throws -> (description: SourceKitLSPAPI.BuildDescription, errors: String) {
351+
// TODO: Remove this workaround once https://github.com/swiftlang/swift-package-manager/issues/8038 is fixed.
352+
var loadAttempt = 0
353+
while true {
354+
loadAttempt += 1
355+
do {
356+
return try await BuildDescription.load(
357+
destinationBuildParameters: destinationBuildParameters,
358+
toolsBuildParameters: toolsBuildParameters,
359+
packageGraph: modulesGraph,
360+
pluginConfiguration: pluginConfiguration,
361+
traitConfiguration: traitConfiguration,
362+
disableSandbox: options.swiftPMOrDefault.disableSandbox ?? false,
363+
scratchDirectory: swiftPMWorkspace.location.scratchDirectory.asURL,
364+
fileSystem: localFileSystem,
365+
observabilityScope: observabilitySystem.topScope.makeChildScope(
366+
description: "Create SwiftPM build description"
367+
)
368+
)
369+
} catch let error as NSError {
370+
#if os(Windows)
371+
if error.domain == NSCocoaErrorDomain, error.code == CocoaError.fileWriteNoPermission.rawValue,
372+
let url = error.userInfo["NSURL"] as? URL, url.lastPathComponent == "output-file-map.json",
373+
loadAttempt < maxLoadAttempts
374+
{
375+
logger.log(
376+
"""
377+
Loading the build description failed to write output-file-map.json \
378+
(attempt \(loadAttempt)/\(maxLoadAttempts)), trying again.
379+
\(error)
380+
"""
381+
)
382+
continue
383+
}
384+
#endif
385+
throw error
386+
}
387+
}
388+
}
389+
344390
/// (Re-)load the package settings by parsing the manifest and resolving all the targets and
345391
/// dependencies.
346392
///
@@ -372,17 +418,7 @@ package actor SwiftPMBuildSystem: BuiltInBuildSystem {
372418
// plugins, without having to worry about messing up any regular build state.
373419
let buildDescription: SourceKitLSPAPI.BuildDescription
374420
if isForIndexBuild && !(options.swiftPMOrDefault.skipPlugins ?? false) {
375-
let loaded = try await BuildDescription.load(
376-
destinationBuildParameters: destinationBuildParameters,
377-
toolsBuildParameters: toolsBuildParameters,
378-
packageGraph: modulesGraph,
379-
pluginConfiguration: pluginConfiguration,
380-
traitConfiguration: traitConfiguration,
381-
disableSandbox: options.swiftPMOrDefault.disableSandbox ?? false,
382-
scratchDirectory: swiftPMWorkspace.location.scratchDirectory.asURL,
383-
fileSystem: localFileSystem,
384-
observabilityScope: observabilitySystem.topScope.makeChildScope(description: "Create SwiftPM build description")
385-
)
421+
let loaded = try await loadBuildDescriptionWithRetryOnOutputFileMapWriteErrorOnWindows(modulesGraph: modulesGraph)
386422
if !loaded.errors.isEmpty {
387423
logger.error("Loading SwiftPM description had errors: \(loaded.errors)")
388424
}

0 commit comments

Comments
 (0)