diff --git a/Package.swift b/Package.swift index 4eac1136f..a994d63bb 100644 --- a/Package.swift +++ b/Package.swift @@ -64,6 +64,7 @@ let package:Package = .init( .library(name: "Symbols", targets: ["Symbols"]), .library(name: "System", targets: ["System"]), + .library(name: "System_ArgumentParser", targets: ["System_ArgumentParser"]), .library(name: "UA", targets: ["UA"]), diff --git a/Sources/SymbolGraphBuilder/Toolchains/SSGC.Toolchain.swift b/Sources/SymbolGraphBuilder/Toolchains/SSGC.Toolchain.swift index a66a700e6..ef0ae3c7e 100644 --- a/Sources/SymbolGraphBuilder/Toolchains/SSGC.Toolchain.swift +++ b/Sources/SymbolGraphBuilder/Toolchains/SSGC.Toolchain.swift @@ -449,6 +449,14 @@ extension SSGC.Toolchain compiler; see https://github.com/apple/swift/issues/68767. """) } + catch SystemProcessError.exit(134, _) + { + print(""" + Failed to dump symbols for module '\(id)' due to SIGABRT \ + from 'swift symbolgraph-extract'. This is a known bug in the Apple Swift \ + compiler; see https://github.com/swiftlang/swift/issues/75318. + """) + } catch SystemProcessError.exit(let code, let invocation) { throw SSGC.PackageBuildError.swift_symbolgraph_extract(code, invocation) diff --git a/Sources/UnidocClient/Unidoc.Client.swift b/Sources/UnidocClient/Unidoc.Client.swift index 147d04bc8..186dda98f 100644 --- a/Sources/UnidocClient/Unidoc.Client.swift +++ b/Sources/UnidocClient/Unidoc.Client.swift @@ -19,15 +19,9 @@ extension Unidoc let executablePath:String? public - let swiftRuntime:String? - public - let swiftPath:String? - public - let swiftSDK:SSGC.AppleSDK? + let authorization:String? public let pretty:Bool - public - let authorization:String? public let http:Protocol @@ -36,11 +30,8 @@ extension Unidoc @inlinable public init( - swiftRuntime:String?, - swiftPath:String?, - swiftSDK:SSGC.AppleSDK?, - pretty:Bool, authorization:String?, + pretty:Bool, http:Protocol, port:Int) { @@ -56,11 +47,8 @@ extension Unidoc self.executablePath = nil #endif - self.swiftRuntime = swiftRuntime - self.swiftPath = swiftPath - self.swiftSDK = swiftSDK - self.pretty = pretty self.authorization = authorization + self.pretty = pretty self.http = http self.port = port } @@ -144,6 +132,7 @@ extension Unidoc.Client labels:Unidoc.BuildLabels, action:Unidoc.LinkerAction, remove:Bool = false, + with toolchain:Unidoc.Toolchain, cache:FilePath? = nil) async throws -> Bool { if let cache:FilePath, remove @@ -218,17 +207,19 @@ extension Unidoc.Client { arguments.append("--pretty") } - if let path:String = self.swiftRuntime + if let usr:FilePath.Directory = toolchain.usr { + let lib:FilePath.Directory = usr / "lib" + arguments.append("--swift-runtime") - arguments.append("\(path)") - } - if let path:String = self.swiftPath - { + arguments.append("\(lib)") + + let swift:FilePath.Directory = usr / "bin" / "swift" + arguments.append("--swift") - arguments.append("\(path)") + arguments.append("\(swift)") } - if let sdk:SSGC.AppleSDK = self.swiftSDK + if let sdk:SSGC.AppleSDK = toolchain.sdk { arguments.append("--sdk") arguments.append("\(sdk)") @@ -293,12 +284,14 @@ extension Unidoc.Client public func buildAndUpload(local symbol:Symbol.Package, - search:FilePath?, - type:SSGC.ProjectType) async throws + search:FilePath.Directory?, + type:SSGC.ProjectType, + with toolchain:Unidoc.Toolchain) async throws { let object:SymbolGraphObject = try await self.build(local: symbol, search: search, - type: type) + type: type, + with: toolchain) try await self.connect { try await $0.upload(object) } @@ -312,12 +305,14 @@ extension Unidoc.Client { public func buildAndUpload(local symbol:Symbol.Package, - search:FilePath?, - type:SSGC.ProjectType) async throws + search:FilePath.Directory?, + type:SSGC.ProjectType, + with toolchain:Unidoc.Toolchain) async throws { let object:SymbolGraphObject = try await self.build(local: symbol, search: search, - type: type) + type: type, + with: toolchain) try await self.connect { try await $0.upload(object) } @@ -331,8 +326,9 @@ extension Unidoc.Client { private func build(local symbol:Symbol.Package, - search:FilePath?, - type:SSGC.ProjectType) async throws -> SymbolGraphObject + search:FilePath.Directory?, + type:SSGC.ProjectType, + with toolchain:Unidoc.Toolchain) async throws -> SymbolGraphObject { let workspace:SSGC.Workspace = try .create(at: ".ssgc") let docs:FilePath = workspace.location / "docs.bson" @@ -349,22 +345,24 @@ extension Unidoc.Client { arguments.append("--pretty") } - if let path:String = self.swiftRuntime + if let usr:FilePath.Directory = toolchain.usr { + let lib:FilePath.Directory = usr / "lib" + arguments.append("--swift-runtime") - arguments.append("\(path)") - } - if let path:String = self.swiftPath - { + arguments.append("\(lib)") + + let swift:FilePath.Directory = usr / "bin" / "swift" + arguments.append("--swift") - arguments.append("\(path)") + arguments.append("\(swift)") } - if let sdk:SSGC.AppleSDK = self.swiftSDK + if let sdk:SSGC.AppleSDK = toolchain.sdk { arguments.append("--sdk") arguments.append("\(sdk)") } - if let search:FilePath = search + if let search:FilePath.Directory { arguments.append("--search-path") arguments.append("\(search)") diff --git a/Sources/UnidocClient/Unidoc.Toolchain.swift b/Sources/UnidocClient/Unidoc.Toolchain.swift new file mode 100644 index 000000000..e52c15405 --- /dev/null +++ b/Sources/UnidocClient/Unidoc.Toolchain.swift @@ -0,0 +1,21 @@ +import SymbolGraphBuilder +import System + +extension Unidoc +{ + @frozen public + struct Toolchain:Equatable, Sendable + { + public + let usr:FilePath.Directory? + public + let sdk:SSGC.AppleSDK? + + @inlinable public + init(usr:FilePath.Directory?, sdk:SSGC.AppleSDK? = nil) + { + self.usr = usr + self.sdk = sdk + } + } +} diff --git a/Sources/unidoc-build/Main.Local.swift b/Sources/unidoc-build/Main.Local.swift index a4c17b508..55a3d7a4f 100644 --- a/Sources/unidoc-build/Main.Local.swift +++ b/Sources/unidoc-build/Main.Local.swift @@ -1,8 +1,10 @@ import ArgumentParser import HTTP +import NIOPosix import SymbolGraphCompiler import Symbols import System +import UnidocClient extension Main { @@ -22,27 +24,21 @@ extension Main var port:Int = 8080 @Option( - name: [.customLong("swift-runtime"), .customShort("r")], - help: "The path to the Swift runtime directory, usually ending in /usr/lib", + name: [.customLong("swift-toolchain"), .customShort("u")], + help: "The path to a Swift toolchain directory, usually ending in 'usr'", completion: .directory) - var swiftRuntime:String? - - @Option( - name: [.customLong("swift"), .customShort("s")], - help: "The path to the Swift toolchain", - completion: .file(extensions: [])) - var swiftPath:String? + var toolchain:FilePath.Directory? @Option( name: [.customLong("swift-sdk"), .customShort("k")], help: "The Swift SDK to use") - var swiftSDK:SSGC.AppleSDK? + var sdk:SSGC.AppleSDK? @Option( name: [.customLong("input"), .customShort("I")], help: "The path to a directory containing the project to build", completion: .directory) - var input:String? + var input:FilePath.Directory? @Flag( @@ -63,16 +59,29 @@ extension Main.Local:AsyncParsableCommand mutating func run() async throws { + let threads:MultiThreadedEventLoopGroup = .init(numberOfThreads: 2) + #if os(macOS) // Guess the SDK if not specified. - self.swiftSDK = self.swiftSDK ?? .macOS + self.sdk = self.sdk ?? .macOS #endif - let search:FilePath? = self.input.map(FilePath.init(_:)) - let type:SSGC.ProjectType = self.book ? .book : .package - let unidoc:Unidoc.Client = try .init(from: self) - try await unidoc.buildAndUpload(local: self.project, search: search, type: type) + let toolchain:Unidoc.Toolchain = .init( + usr: self.toolchain, + sdk: self.sdk) + + let unidoc:Unidoc.Client = .init(authorization: nil, + pretty: self.pretty, + http: .init(threads: threads, niossl: nil, remote: self.host), + port: self.port) + + print("Connecting to \(self.host):\(self.port)...") + + try await unidoc.buildAndUpload(local: self.project, + search: self.input, + type: self.book ? .book : .package, + with: toolchain) } } diff --git a/Sources/unidoc-build/Unidoc.Client (ext).swift b/Sources/unidoc-build/Unidoc.Client (ext).swift deleted file mode 100644 index 93405ce02..000000000 --- a/Sources/unidoc-build/Unidoc.Client (ext).swift +++ /dev/null @@ -1,22 +0,0 @@ -import HTTP -import NIOPosix -import UnidocClient - -extension Unidoc.Client -{ - init(from options:Main.Local) throws - { - let threads:MultiThreadedEventLoopGroup = .init(numberOfThreads: 2) - - print("Connecting to \(options.host):\(options.port)...") - - self.init( - swiftRuntime: options.swiftRuntime, - swiftPath: options.swiftPath, - swiftSDK: options.swiftSDK, - pretty: options.pretty, - authorization: nil, - http: .init(threads: threads, niossl: nil, remote: options.host), - port: options.port) - } -}