From 7da61148f33c8f0c26bcdbffeacc511ec50a7b36 Mon Sep 17 00:00:00 2001 From: Kabir Oberai Date: Mon, 25 May 2026 05:55:37 -0400 Subject: [PATCH] SWBBuild SDK support --- Sources/XToolSupport/SDKBuilder.swift | 72 +++++++++++++++++++++++---- 1 file changed, 61 insertions(+), 11 deletions(-) diff --git a/Sources/XToolSupport/SDKBuilder.swift b/Sources/XToolSupport/SDKBuilder.swift index 44fc8fb..04000da 100644 --- a/Sources/XToolSupport/SDKBuilder.swift +++ b/Sources/XToolSupport/SDKBuilder.swift @@ -136,6 +136,9 @@ struct SDKBuilder { "linker": { "path": "ld64.lld" }, + "librarian": { + "path": "llvm-lib" + }, "swiftCompiler": { "extraCLIOptions": [ "-Xfrontend", "-enable-cross-import-overlays", @@ -149,6 +152,24 @@ struct SDKBuilder { encoding: .utf8 ) + // this toolset works with the swiftbuild system + try """ + { + "schemaVersion": "1.0", + "rootPath": "toolset/bin", + "linker": { + "path": "ld" + }, + "librarian": { + "path": "llvm-lib" + } + } + """.write( + to: output.appendingPathComponent("toolset-swb.json"), + atomically: false, + encoding: .utf8 + ) + let sdkDefinition = SDKDefinition( schemaVersion: "4.0", targetTriples: [ @@ -215,6 +236,16 @@ struct SDKBuilder { try await input.finish() } .checkSuccess() + + // swift-build assumes we have an Apple-flavored librarian for Apple platforms + // (https://github.com/swiftlang/swift-build/blob/b2433e74e/Sources/SWBCore/SpecImplementations/Tools/LinkerTools.swift#L1735) + // but allows us to override this assumption if we explicitly provide the name llvm-lib (look a few lines above in that file) + try FileManager.default.moveItem( + at: toolsetDir.appending(path: "bin/libtool"), + to: toolsetDir.appending(path: "bin/llvm-lib") + ) + + // TODO: install cctools ld as well } // swiftlint:disable:next cyclomatic_complexity @@ -321,10 +352,11 @@ struct SDKBuilder { for platform in ["iPhoneOS", "MacOSX", "iPhoneSimulator"] { let lib = "../../../../../Library" - let dest = dev.appendingPathComponent(""" - Platforms/\(platform).platform/Developer/SDKs/\(platform).sdk\ - /System/Library/Frameworks - """).path + let sdkDir = dev.appending(path: "Platforms/\(platform).platform/Developer/SDKs/\(platform).sdk") + + try patchSDKSettings(path: sdkDir.appending(path: "SDKSettings.plist")) + + let dest = sdkDir.appending(path: "System/Library/Frameworks").path try FileManager.default.createSymbolicLink( atPath: "\(dest)/Testing.framework", @@ -354,6 +386,21 @@ struct SDKBuilder { return dev } + private func patchSDKSettings(path: URL) throws { + let data = try Data(contentsOf: path) + guard var plist = try PropertyListSerialization.propertyList(from: data, options: [], format: nil) as? [String: Any] else { + throw Console.Error("Could not read SDKSettings.plist at '\(path.path)'") + } + + var customProperties = (plist["CustomProperties"] as? [String: Any]) ?? [:] + customProperties["SWIFT_RESOURCE_DIR"] = "$(PLATFORM_DIR)/../../Toolchains/XcodeDefault.xctoolchain/usr/lib/swift" + customProperties["CLANG_RESOURCE_DIR"] = "$(SYSTEM_DEVELOPER_USR_DIR)/lib/swift/clang" + plist["CustomProperties"] = customProperties + + let newData = try PropertyListSerialization.data(fromPropertyList: plist, format: .xml, options: 0) + try newData.write(to: path) + } + // returns the number of files we actually want to keep, // useful for computing progress % during fs traversal private func extractXIP(inputPath: String, outDir: String) async throws -> Int { @@ -497,13 +544,16 @@ struct SDKEntry { E("clang"), ]), E("Platforms", ["iPhoneOS", "MacOSX", "iPhoneSimulator"].map { - E("\($0).platform/Developer", [ - E("SDKs"), - E("Library", [ - E("Frameworks"), - E("PrivateFrameworks"), - ]), - E("usr/lib"), + E("\($0).platform", [ + E("Info.plist"), + E("Developer", [ + E("SDKs"), + E("Library", [ + E("Frameworks"), + E("PrivateFrameworks"), + ]), + E("usr/lib"), + ]) ]) }), ])