diff --git a/Documentation/Configuration File.md b/Documentation/Configuration File.md index fad3c396b..e27dd7704 100644 --- a/Documentation/Configuration File.md +++ b/Documentation/Configuration File.md @@ -13,12 +13,15 @@ The structure of the file is currently not guaranteed to be stable. Options may `config.json` is a JSON file with the following structure. All keys are optional and unknown keys are ignored. - `swiftPM`: Dictionary with the following keys, defining options for SwiftPM workspaces - - `configuration: "debug"|"release"`: The configuration to build the project for during background indexing and the configuration whose build folder should be used for Swift modules if background indexing is disabled - - `scratchPath: string`: Build artifacts directory path. If nil, the build system may choose a default value - - `cCompilerFlags: string[]`: Extra arguments passed to the compiler for C files - - `cxxCompilerFlags: string[]`: Extra arguments passed to the compiler for C++ files - - `swiftCompilerFlags: string[]`: Extra arguments passed to the compiler for Swift files - - `linkerFlags: string[]`: Extra arguments passed to the linker + - `configuration: "debug"|"release"`: The configuration to build the project for during background indexing and the configuration whose build folder should be used for Swift modules if background indexing is disabled. Equivalent to SwiftPM's `--configuration` option. + - `scratchPath: string`: Build artifacts directory path. If nil, the build system may choose a default value. Equivalent to SwiftPM's `--scratch-path` option. + - `swiftSDKsDirectory: string`: Equivalent to SwiftPM's `--swift-sdks-path` option + - `swiftSDK: string`: Equivalent to SwiftPM's `--swift-sdk` option + - `triple: string`: Equivalent to SwiftPM's `--triple` option + - `cCompilerFlags: string[]`: Extra arguments passed to the compiler for C files. Equivalent to SwiftPM's `-Xcc` option. + - `cxxCompilerFlags: string[]`: Extra arguments passed to the compiler for C++ files. Equivalent to SwiftPM's `-Xcxx` option. + - `swiftCompilerFlags: string[]`: Extra arguments passed to the compiler for Swift files. Equivalent to SwiftPM's `-Xswiftc` option. + - `linkerFlags: string[]`: Extra arguments passed to the linker. Equivalent to SwiftPM's `-Xlinker` option. - `compilationDatabase`: Dictionary with the following keys, defining options for workspaces with a compilation database - `searchPaths: string[]`: Additional paths to search for a compilation database, relative to a workspace root. - `fallbackBuildSystem`: Dictionary with the following keys, defining options for files that aren't managed by any build system diff --git a/Sources/SKCore/SourceKitLSPOptions.swift b/Sources/SKCore/SourceKitLSPOptions.swift index 0a9ad011a..e9bd54666 100644 --- a/Sources/SKCore/SourceKitLSPOptions.swift +++ b/Sources/SKCore/SourceKitLSPOptions.swift @@ -23,19 +23,42 @@ import struct TSCBasic.AbsolutePath public struct SourceKitLSPOptions: Sendable, Codable { public struct SwiftPMOptions: Sendable, Codable { /// Build configuration (debug|release). + /// + /// Equivalent to SwiftPM's `--configuration` option. public var configuration: BuildConfiguration? /// Build artifacts directory path. If nil, the build system may choose a default value. + /// + /// Equivalent to SwiftPM's `--scratch-path` option. public var scratchPath: String? + /// Equivalent to SwiftPM's `--swift-sdks-path` option + public var swiftSDKsDirectory: String? + + /// Equivalent to SwiftPM's `--swift-sdk` option + public var swiftSDK: String? + + /// Equivalent to SwiftPM's `--triple` option + public var triple: String? + + /// Equivalent to SwiftPM's `-Xcc` option public var cCompilerFlags: [String]? + + /// Equivalent to SwiftPM's `-Xcxx` option public var cxxCompilerFlags: [String]? + + /// Equivalent to SwiftPM's `-Xswiftc` option public var swiftCompilerFlags: [String]? + + /// Equivalent to SwiftPM's `-Xlinker` option public var linkerFlags: [String]? public init( configuration: BuildConfiguration? = nil, scratchPath: String? = nil, + swiftSDKsDirectory: String? = nil, + swiftSDK: String? = nil, + triple: String? = nil, cCompilerFlags: [String]? = nil, cxxCompilerFlags: [String]? = nil, swiftCompilerFlags: [String]? = nil, @@ -43,6 +66,9 @@ public struct SourceKitLSPOptions: Sendable, Codable { ) { self.configuration = configuration self.scratchPath = scratchPath + self.swiftSDKsDirectory = swiftSDKsDirectory + self.swiftSDK = swiftSDK + self.triple = triple self.cCompilerFlags = cCompilerFlags self.cxxCompilerFlags = cxxCompilerFlags self.swiftCompilerFlags = swiftCompilerFlags @@ -53,6 +79,9 @@ public struct SourceKitLSPOptions: Sendable, Codable { return SwiftPMOptions( configuration: override?.configuration ?? base.configuration, scratchPath: override?.scratchPath ?? base.scratchPath, + swiftSDKsDirectory: override?.swiftSDKsDirectory ?? base.swiftSDKsDirectory, + swiftSDK: override?.swiftSDK ?? base.swiftSDK, + triple: override?.triple ?? base.triple, cCompilerFlags: override?.cCompilerFlags ?? base.cCompilerFlags, cxxCompilerFlags: override?.cxxCompilerFlags ?? base.cxxCompilerFlags, swiftCompilerFlags: override?.swiftCompilerFlags ?? base.swiftCompilerFlags, diff --git a/Sources/SKSwiftPMWorkspace/SwiftPMBuildSystem.swift b/Sources/SKSwiftPMWorkspace/SwiftPMBuildSystem.swift index 0f47fa071..04ffa19fc 100644 --- a/Sources/SKSwiftPMWorkspace/SwiftPMBuildSystem.swift +++ b/Sources/SKSwiftPMWorkspace/SwiftPMBuildSystem.swift @@ -222,8 +222,29 @@ public actor SwiftPMBuildSystem { throw Error.cannotDetermineHostToolchain } - let swiftSDK = try SwiftSDK.hostSwiftSDK(AbsolutePath(destinationToolchainBinDir)) - let swiftPMToolchain = try UserToolchain(swiftSDK: swiftSDK) + let hostSDK = try SwiftSDK.hostSwiftSDK(AbsolutePath(destinationToolchainBinDir)) + let hostSwiftPMToolchain = try UserToolchain(swiftSDK: hostSDK) + + var destinationSDK: SwiftSDK + if let swiftSDK = options.swiftSDK { + let bundleStore = try SwiftSDKBundleStore( + swiftSDKsDirectory: fileSystem.getSharedSwiftSDKsDirectory( + explicitDirectory: options.swiftSDKsDirectory.map { try AbsolutePath(validating: $0) } + ), + fileSystem: fileSystem, + observabilityScope: observabilitySystem.topScope, + outputHandler: { _ in } + ) + destinationSDK = try bundleStore.selectBundle(matching: swiftSDK, hostTriple: hostSwiftPMToolchain.targetTriple) + } else { + destinationSDK = hostSDK + } + + if let triple = options.triple { + destinationSDK = hostSDK + destinationSDK.targetTriple = try Triple(triple) + } + let destinationSwiftPMToolchain = try UserToolchain(swiftSDK: destinationSDK) var location = try Workspace.Location( forRootPackage: AbsolutePath(packageRoot), @@ -244,7 +265,7 @@ public actor SwiftPMBuildSystem { fileSystem: fileSystem, location: location, configuration: configuration, - customHostToolchain: swiftPMToolchain + customHostToolchain: hostSwiftPMToolchain ) let buildConfiguration: PackageModel.BuildConfiguration @@ -265,20 +286,21 @@ public actor SwiftPMBuildSystem { self.toolsBuildParameters = try BuildParameters( destination: .host, dataPath: location.scratchDirectory.appending( - component: swiftPMToolchain.targetTriple.platformBuildPathComponent + component: hostSwiftPMToolchain.targetTriple.platformBuildPathComponent ), configuration: buildConfiguration, - toolchain: swiftPMToolchain, + toolchain: hostSwiftPMToolchain, flags: buildFlags ) self.destinationBuildParameters = try BuildParameters( destination: .target, dataPath: location.scratchDirectory.appending( - component: swiftPMToolchain.targetTriple.platformBuildPathComponent + component: destinationSwiftPMToolchain.targetTriple.platformBuildPathComponent ), configuration: buildConfiguration, - toolchain: swiftPMToolchain, + toolchain: destinationSwiftPMToolchain, + triple: destinationSDK.targetTriple, flags: buildFlags ) diff --git a/Tests/SourceKitLSPTests/SwiftPMIntegration.swift b/Tests/SourceKitLSPTests/SwiftPMIntegration.swift index 5944828dc..86e308acd 100644 --- a/Tests/SourceKitLSPTests/SwiftPMIntegration.swift +++ b/Tests/SourceKitLSPTests/SwiftPMIntegration.swift @@ -241,4 +241,53 @@ final class SwiftPMIntegrationTests: XCTestCase { ] ) } + + func testWasm() async throws { + let project = try await SwiftPMTestProject( + files: [ + "/.sourcekit-lsp/config.json": """ + { + "swiftPM": { + "triple": "wasm32-unknown-none-wasm" + } + } + """, + "Test.swift": """ + #if arch(wasm32) + let _: UnsafeRawPointer = 1 + #endif + """, + ], + manifest: """ + let package = Package( + name: "WasmTest", + targets: [ + .executableTarget( + name: "wasmTest", + cSettings: [.unsafeFlags(["-fdeclspec"])], + swiftSettings: [ + .enableExperimentalFeature("Embedded"), + .interoperabilityMode(.Cxx), + .unsafeFlags(["-wmo", "-disable-cmo", "-Xfrontend", "-gnone"]), + ], + linkerSettings: [.unsafeFlags(["-Xclang-linker", "-nostdlib", "-Xlinker", "--no-entry"])] + ) + ] + ) + """ + ) + + let (uri, _) = try project.openDocument("Test.swift") + let diagnostics = try await project.testClient.send( + DocumentDiagnosticsRequest(textDocument: TextDocumentIdentifier(uri)) + ) + guard case .full(let diagnostics) = diagnostics else { + XCTFail("Expected full diagnostics report") + return + } + XCTAssertEqual( + diagnostics.items.map(\.message), + ["Cannot convert value of type 'Int' to specified type 'UnsafeRawPointer'"] + ) + } }