Description
Swift package manager can no longer communicate properly with swift build over its dispatch queue.
This only occurs on Windows.
Swift package manager is being updated to be able to use swift-build as its backend build system. When running swift package commands using the swift-build backend and using swift 6.2, a send to swift-build blocks forever.
I have traced it down to differences in dispatch.dll
This can be reproduced as follows.
Download/Install 6.2 Toolchain
mkdir example
cd example
swift package init --type tool --name swift-build-hang
swift build --vv --build-system swiftbuild
This will hang as such (most of the time on first message to swift-build, it may get one or two messages thru)
debug: PIF: Processing 1 modules:
debug: PIF: Created target 'PACKAGE-TARGET:swift-build-hang--17122C12685F4EBB-testable' of type 'objectFile' with name 'swift-build-hang' and product name 'swift-build-hang.o'
debug: PIF: Added '["$(inherited)"]' to imparted OTHER_LDFLAGS
debug: PIF: Added '["$(BUILT_PRODUCTS_DIR)/PackageFrameworks", "$(inherited)"]' to imparted FRAMEWORK_SEARCH_PATHS
debug: PIF: Added source file group 'C:\Users\kcieplak\example\Sources\swift-build-hang'
debug: PIF: Added source file 'swift_build_hang.swift'
debug: PIF: Added dependency on product 'PACKAGE-PRODUCT:ArgumentParser'
debug: PIF: Created project 'AGGREGATE' with name 'Aggregate'
debug: PIF: Created target 'ALL-INCLUDING-TESTS' with name 'AllIncludingTests' and 2 (unlinked) dependencies
debug: PIF: Created target 'ALL-EXCLUDING-TESTS' with name 'AllExcludingTests' and 2 (unlinked) dependencies
Now to revert the dispatch.dll to a 6.1.X variant.
cd <ToolchainDir>
cd "c:\Users\kcieplak\AppData\Local\Programs\Swift\Toolchains\6.2.0+Asserts\usr\bin"
copy libdispatch.dll libdispatch.dll.orig
copy "c:\Users\kcieplak\AppData\Local\Programs\Swift -6.1.1\Runtimes\6.1.0\usr\bin\dispatch.dll" dispatch.dll
Overwrite dispatch.dll? (Yes/No/All): Y
1 file(s) copied.
Run again
swift build --vv --build-system swiftbuild
Things begin to work consistently again.
debug: PIF: Created target 'ALL-INCLUDING-TESTS' with name 'AllIncludingTests' and 2 (unlinked) dependencies
debug: PIF: Created target 'ALL-EXCLUDING-TESTS' with name 'AllExcludingTests' and 2 (unlinked) dependencies
info: Compute target dependency graph
Building for debugging...
0%: Computing dependencies
info: Building targets in dependency order
info: Target dependency graph (6 targets)
info: Target 'AllExcludingTests' in project 'Aggregate'
0%: Provisioning 3 / 6
info: ➜ Explicit dependency on target 'swift-build-hang-product' in project 'swift-build-hang'
info: ➜ Explicit dependency on target 'swift-build-hang' in project 'swift-build-hang'
info: Target 'swift-build-hang' in project 'swift-build-hang'
info: ➜ Explicit dependency on target 'ArgumentParser-product' in project 'swift-argument-parser'
info: Target 'swift-build-hang-product' in project 'swift-build-hang'
info: ➜ Explicit dependency on target 'ArgumentParser-product' in project 'swift-argument-parser'
.....
swift-package-manager uses a send queue that uses dispatch under the covers.
SPM message send
public func loadWorkspace(containerPath: String) async throws {
_ = try await service.send(request: SetSessionWorkspaceContainerPathRequest(sessionHandle: uid, containerPath: containerPath))
}
swift-build has its messaging interface implemented using dispatch.
I have locally built dispatch.dll and can confirm that the issue does not happen for the release/6.1 branch.
I suspect it has to do with this change:
#842