From 01fe9b820b936a3d8254cde19a459d0253e8bac8 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Fri, 26 Dec 2025 13:38:58 +0900 Subject: [PATCH 1/6] SwiftSDK: Support specifying metadata JSON path as an artifact variant An artifact variant path allows specifying either a directory containing a `swift-sdk.json` file or the path to the `swift-sdk.json` file itself. Swift SDK for WebAssembly uses this feature to collocate regular SDK and embedded SDK. --- Sources/SWBCore/SwiftSDK.swift | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/Sources/SWBCore/SwiftSDK.swift b/Sources/SWBCore/SwiftSDK.swift index c8f7f43f..3e24c1cf 100644 --- a/Sources/SWBCore/SwiftSDK.swift +++ b/Sources/SWBCore/SwiftSDK.swift @@ -52,13 +52,10 @@ public struct SwiftSDK: Sendable { /// Target-specific properties for this SDK. public let targetTriples: [String: TripleProperties] - init?(identifier: String, version: String, path: Path, fs: any FSProxy) throws { + init?(identifier: String, version: String, metadataPath: Path, fs: any FSProxy) throws { self.identifier = identifier self.version = version - self.path = path - - let metadataPath = path.join("swift-sdk.json") - guard fs.exists(metadataPath) else { return nil } + self.path = metadataPath.dirname let metadataData = try Data(fs.read(metadataPath)) let schema = try JSONDecoder().decode(SchemaVersionInfo.self, from: metadataData) @@ -137,13 +134,20 @@ public struct SwiftSDK: Sendable { for (identifier, artifact) in info.artifacts { for variant in artifact.variants { - let sdkPath = artifactBundle.join(variant.path) - guard fs.isDirectory(sdkPath) else { continue } + // A variant's path may be a directory or a file. If it's a directory, we assume it + // contains a swift-sdk.json file. If it's a file, we use it directly as a Swift SDK + // metadata file. + var sdkPath = artifactBundle.join(variant.path) + if sdkPath.fileExtension != "json" && fs.isDirectory(sdkPath) { + sdkPath = sdkPath.join("swift-sdk.json") + } + + guard fs.exists(sdkPath) else { continue } // FIXME: For now, we only support SDKs that are compatible with any host triple. guard variant.supportedTriples?.isEmpty ?? true else { continue } - guard let sdk = try SwiftSDK(identifier: identifier, version: artifact.version, path: sdkPath, fs: fs) else { continue } + guard let sdk = try SwiftSDK(identifier: identifier, version: artifact.version, metadataPath: sdkPath, fs: fs) else { continue } // Filter out SDKs that don't support any of the target triples. if let targetTriples { guard targetTriples.contains(where: { sdk.targetTriples[$0] != nil }) else { continue } From 0dd9a923357d2394e9d1e2ecca6c2b04e06e4b25 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Fri, 26 Dec 2025 13:44:21 +0900 Subject: [PATCH 2/6] SwiftSDK: Fix default Swift SDKs directory to respect XDG_CONFIG_HOME on non-macOS --- Sources/SWBCore/SwiftSDK.swift | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Sources/SWBCore/SwiftSDK.swift b/Sources/SWBCore/SwiftSDK.swift index 3e24c1cf..d695b3df 100644 --- a/Sources/SWBCore/SwiftSDK.swift +++ b/Sources/SWBCore/SwiftSDK.swift @@ -67,6 +67,8 @@ public struct SwiftSDK: Sendable { /// The default location storing Swift SDKs installed by SwiftPM. static func defaultSwiftSDKsDirectory(hostOperatingSystem: OperatingSystem) throws -> Path { + // NOTE: Keep in sync with SwiftPM's defaultSwiftSDKsDirectory implementation. + // https://github.com/swiftlang/swift-package-manager/blob/deac56dc94d85d28f2f2b5c37ec347ae3523a3fe/Sources/Basics/FileSystem/FileSystem%2BExtensions.swift#L492 let spmURL: URL if hostOperatingSystem == .macOS { spmURL = try FileManager.default.url( @@ -76,7 +78,11 @@ public struct SwiftSDK: Sendable { create: false ).appendingPathComponent("org.swift.swiftpm") } else { - spmURL = URL.homeDirectory.appendingPathComponent(".swiftpm") + if let configurationDirectory = Environment.current["XDG_CONFIG_HOME"] { + spmURL = URL(fileURLWithPath: configurationDirectory, isDirectory: true).appendingPathComponent("swiftpm") + } else { + spmURL = URL.homeDirectory.appendingPathComponent(".swiftpm") + } } return try spmURL.appendingPathComponent("swift-sdks").filePath } From d47d3b7521287323b7f27b25dee2c72e36995d48 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Fri, 26 Dec 2025 16:45:25 +0900 Subject: [PATCH 3/6] Wasm: Remove obsolete linker flags hacks now that swiftc linker driver is supported After https://github.com/swiftlang/swift-build/pull/236, we no longer need to manually add Swift specific linker flags in the WebAssembly SDK. --- Sources/SWBWebAssemblyPlatform/Plugin.swift | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Sources/SWBWebAssemblyPlatform/Plugin.swift b/Sources/SWBWebAssemblyPlatform/Plugin.swift index dbc99e82..edae8d63 100644 --- a/Sources/SWBWebAssemblyPlatform/Plugin.swift +++ b/Sources/SWBWebAssemblyPlatform/Plugin.swift @@ -106,10 +106,6 @@ struct WebAssemblySDKRegistryExtension: SDKRegistryExtension { "LLVM_TARGET_TRIPLE_OS_VERSION": .plString(os), "SWIFT_LIBRARY_PATH": .plString(swiftResourceDir.join("wasi").str), "SWIFT_RESOURCE_DIR": .plString(swiftResourceDir.str), - // HACK: Ld step does not use swiftc as linker driver but instead uses clang, so we need to add some Swift specific flags - // assuming static linking. - // Tracked in https://github.com/swiftlang/swift-build/issues/3 - "OTHER_LDFLAGS": .plArray(["-lc++", "-lc++abi", "-resource-dir", "$(SWIFT_RESOURCE_DIR)/clang", "@$(SWIFT_LIBRARY_PATH)/static-executable-args.lnk"]), ]), "SupportedTargets": .plDict([ "webassembly": .plDict([ From 8f0d3c69dd2fb28f50535dbb75aa7f6936f2bf32 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Fri, 26 Dec 2025 16:49:00 +0900 Subject: [PATCH 4/6] Wasm: Pass `-resource-dir` to linker driver Some targets use the resource dir during linking to find files like `static-executable-args.lnk` in swift-driver and compiler-rt libraries in clang. They are normally located under the Swift `-sdk` path or `-sysroot` path, but Swift SDK for Wasm located resource dirs outside of `-sdk`/`-sysroot` path. This patch adds `-resource-dir` flag to the linker driver invocation. --- .../SWBWebAssemblyPlatform/Specs/WasmLd.xcspec | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Sources/SWBWebAssemblyPlatform/Specs/WasmLd.xcspec b/Sources/SWBWebAssemblyPlatform/Specs/WasmLd.xcspec index ba106172..6839212b 100644 --- a/Sources/SWBWebAssemblyPlatform/Specs/WasmLd.xcspec +++ b/Sources/SWBWebAssemblyPlatform/Specs/WasmLd.xcspec @@ -148,6 +148,21 @@ Type = Path; Condition = "NO"; // wasm-ld does not support -filelist }, + { + Name = "SWIFTC_LINKER_RESOURCE_DIR"; + Type = Path; + DefaultValue = "$(SWIFT_RESOURCE_DIR)"; + Condition = "$(LINKER_DRIVER) == swiftc"; + CommandLineArgs = ( + "-resource-dir", + "$(value)", + "-Xclang-linker", + "-resource-dir", + "-Xclang-linker", + "$(value)/clang", + ); + IsInputDependency = Yes; + }, ); }, ) From e725a47fe5b3a789169583842fb014aacb1c4d5b Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Fri, 26 Dec 2025 16:54:35 +0900 Subject: [PATCH 5/6] Wasm: Override SWIFTC_SDKROOT_LINKER_INPUT to use `-sdk` over `-sysroot` for now The override is needed because swift-driver currently does not respect `-sysroot` for Wasm targets, but only `-sdk`. This will be fixed in swift-driver in the change: https://github.com/swiftlang/swift-driver/pull/2053 --- Sources/SWBWebAssemblyPlatform/Specs/WasmLd.xcspec | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Sources/SWBWebAssemblyPlatform/Specs/WasmLd.xcspec b/Sources/SWBWebAssemblyPlatform/Specs/WasmLd.xcspec index 6839212b..2fb21519 100644 --- a/Sources/SWBWebAssemblyPlatform/Specs/WasmLd.xcspec +++ b/Sources/SWBWebAssemblyPlatform/Specs/WasmLd.xcspec @@ -163,6 +163,15 @@ ); IsInputDependency = Yes; }, + // TODO(yuta): Remove this override entry after https://github.com/swiftlang/swift-driver/pull/2053 + { + Name = SWIFTC_SDKROOT_LINKER_INPUT; + Type = Path; + DefaultValue = "$(SYSROOT:default=$(SDKROOT))"; + Condition = "$(LINKER_DRIVER) == swiftc"; + CommandLineFlag = "-sdk"; + IsInputDependency = Yes; + }, ); }, ) From 7f3e76768350c028d85579517c031f826f2a72f3 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Fri, 26 Dec 2025 21:52:24 +0900 Subject: [PATCH 6/6] SWBCore: Impose SDKROOT only if SDK is available --- Sources/SWBCore/DependencyResolution.swift | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Sources/SWBCore/DependencyResolution.swift b/Sources/SWBCore/DependencyResolution.swift index 80343091..9848aada 100644 --- a/Sources/SWBCore/DependencyResolution.swift +++ b/Sources/SWBCore/DependencyResolution.swift @@ -206,7 +206,17 @@ struct SpecializationParameters: Hashable, CustomStringConvertible { func imposed(on parameters: BuildParameters, workspaceContext: WorkspaceContext) -> BuildParameters { var overrides = parameters.overrides if let sdkRoot { - overrides["SDKROOT"] = sdkRoot + // The sdkCanonicalName from a Platform is not guaranteed to be available + let defaultSDKAvailable: Bool + do { + let foundSDK = try workspaceContext.core.sdkRegistry.lookup(sdkRoot, activeRunDestination: parameters.activeRunDestination) + defaultSDKAvailable = foundSDK != nil + } catch { + defaultSDKAvailable = false + } + if defaultSDKAvailable { + overrides["SDKROOT"] = sdkRoot + } } if let sdkVariant { overrides["SDK_VARIANT"] = sdkVariant.name