Skip to content

Commit f64f6fa

Browse files
committed
Support using SourceKit-LSP for projects that are cross-compiled
We previously always assumed that the project was being built for the host. Fixes #1475 rdar://129662080
1 parent abfe5e9 commit f64f6fa

File tree

4 files changed

+116
-13
lines changed

4 files changed

+116
-13
lines changed

Documentation/Configuration File.md

+9-6
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,15 @@ The structure of the file is currently not guaranteed to be stable. Options may
1313
`config.json` is a JSON file with the following structure. All keys are optional and unknown keys are ignored.
1414

1515
- `swiftPM`: Dictionary with the following keys, defining options for SwiftPM workspaces
16-
- `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
17-
- `scratchPath: string`: Build artifacts directory path. If nil, the build system may choose a default value
18-
- `cCompilerFlags: string[]`: Extra arguments passed to the compiler for C files
19-
- `cxxCompilerFlags: string[]`: Extra arguments passed to the compiler for C++ files
20-
- `swiftCompilerFlags: string[]`: Extra arguments passed to the compiler for Swift files
21-
- `linkerFlags: string[]`: Extra arguments passed to the linker
16+
- `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.
17+
- `scratchPath: string`: Build artifacts directory path. If nil, the build system may choose a default value. Equivalent to SwiftPM's `--scratch-path` option.
18+
- `swiftSDKsDirectory: string`: Equivalent to SwiftPM's `--swift-sdks-path` option
19+
- `swiftSDK: string`: Equivalent to SwiftPM's `--swift-sdk` option
20+
- `triple: string`: Equivalent to SwiftPM's `--triple` option
21+
- `cCompilerFlags: string[]`: Extra arguments passed to the compiler for C files. Equivalent to SwiftPM's `-Xcc` option.
22+
- `cxxCompilerFlags: string[]`: Extra arguments passed to the compiler for C++ files. Equivalent to SwiftPM's `-Xcxx` option.
23+
- `swiftCompilerFlags: string[]`: Extra arguments passed to the compiler for Swift files. Equivalent to SwiftPM's `-Xswiftc` option.
24+
- `linkerFlags: string[]`: Extra arguments passed to the linker. Equivalent to SwiftPM's `-Xlinker` option.
2225
- `compilationDatabase`: Dictionary with the following keys, defining options for workspaces with a compilation database
2326
- `searchPaths: string[]`: Additional paths to search for a compilation database, relative to a workspace root.
2427
- `fallbackBuildSystem`: Dictionary with the following keys, defining options for files that aren't managed by any build system

Sources/SKCore/SourceKitLSPOptions.swift

+29
Original file line numberDiff line numberDiff line change
@@ -23,26 +23,52 @@ import struct TSCBasic.AbsolutePath
2323
public struct SourceKitLSPOptions: Sendable, Codable {
2424
public struct SwiftPMOptions: Sendable, Codable {
2525
/// Build configuration (debug|release).
26+
///
27+
/// Equivalent to SwiftPM's `--configuration` option.
2628
public var configuration: BuildConfiguration?
2729

2830
/// Build artifacts directory path. If nil, the build system may choose a default value.
31+
///
32+
/// Equivalent to SwiftPM's `--scratch-path` option.
2933
public var scratchPath: String?
3034

35+
/// Equivalent to SwiftPM's `--swift-sdks-path` option
36+
public var swiftSDKsDirectory: String?
37+
38+
/// Equivalent to SwiftPM's `--swift-sdk` option
39+
public var swiftSDK: String?
40+
41+
/// Equivalent to SwiftPM's `--triple` option
42+
public var triple: String?
43+
44+
/// Equivalent to SwiftPM's `-Xcc` option
3145
public var cCompilerFlags: [String]?
46+
47+
/// Equivalent to SwiftPM's `-Xcxx` option
3248
public var cxxCompilerFlags: [String]?
49+
50+
/// Equivalent to SwiftPM's `-Xswiftc` option
3351
public var swiftCompilerFlags: [String]?
52+
53+
/// Equivalent to SwiftPM's `-Xlinker` option
3454
public var linkerFlags: [String]?
3555

3656
public init(
3757
configuration: BuildConfiguration? = nil,
3858
scratchPath: String? = nil,
59+
swiftSDKsDirectory: String? = nil,
60+
swiftSDK: String? = nil,
61+
triple: String? = nil,
3962
cCompilerFlags: [String]? = nil,
4063
cxxCompilerFlags: [String]? = nil,
4164
swiftCompilerFlags: [String]? = nil,
4265
linkerFlags: [String]? = nil
4366
) {
4467
self.configuration = configuration
4568
self.scratchPath = scratchPath
69+
self.swiftSDKsDirectory = swiftSDKsDirectory
70+
self.swiftSDK = swiftSDK
71+
self.triple = triple
4672
self.cCompilerFlags = cCompilerFlags
4773
self.cxxCompilerFlags = cxxCompilerFlags
4874
self.swiftCompilerFlags = swiftCompilerFlags
@@ -53,6 +79,9 @@ public struct SourceKitLSPOptions: Sendable, Codable {
5379
return SwiftPMOptions(
5480
configuration: override?.configuration ?? base.configuration,
5581
scratchPath: override?.scratchPath ?? base.scratchPath,
82+
swiftSDKsDirectory: override?.swiftSDKsDirectory ?? base.swiftSDKsDirectory,
83+
swiftSDK: override?.swiftSDK ?? base.swiftSDK,
84+
triple: override?.triple ?? base.triple,
5685
cCompilerFlags: override?.cCompilerFlags ?? base.cCompilerFlags,
5786
cxxCompilerFlags: override?.cxxCompilerFlags ?? base.cxxCompilerFlags,
5887
swiftCompilerFlags: override?.swiftCompilerFlags ?? base.swiftCompilerFlags,

Sources/SKSwiftPMWorkspace/SwiftPMBuildSystem.swift

+29-7
Original file line numberDiff line numberDiff line change
@@ -222,8 +222,29 @@ public actor SwiftPMBuildSystem {
222222
throw Error.cannotDetermineHostToolchain
223223
}
224224

225-
let swiftSDK = try SwiftSDK.hostSwiftSDK(AbsolutePath(destinationToolchainBinDir))
226-
let swiftPMToolchain = try UserToolchain(swiftSDK: swiftSDK)
225+
let hostSDK = try SwiftSDK.hostSwiftSDK(AbsolutePath(destinationToolchainBinDir))
226+
let hostSwiftPMToolchain = try UserToolchain(swiftSDK: hostSDK)
227+
228+
var destinationSDK: SwiftSDK
229+
if let swiftSDK = options.swiftSDK {
230+
let bundleStore = try SwiftSDKBundleStore(
231+
swiftSDKsDirectory: fileSystem.getSharedSwiftSDKsDirectory(
232+
explicitDirectory: options.swiftSDKsDirectory.map { try AbsolutePath(validating: $0) }
233+
),
234+
fileSystem: fileSystem,
235+
observabilityScope: observabilitySystem.topScope,
236+
outputHandler: { _ in }
237+
)
238+
destinationSDK = try bundleStore.selectBundle(matching: swiftSDK, hostTriple: hostSwiftPMToolchain.targetTriple)
239+
} else {
240+
destinationSDK = hostSDK
241+
}
242+
243+
if let triple = options.triple {
244+
destinationSDK = hostSDK
245+
destinationSDK.targetTriple = try Triple(triple)
246+
}
247+
let destinationSwiftPMToolchain = try UserToolchain(swiftSDK: destinationSDK)
227248

228249
var location = try Workspace.Location(
229250
forRootPackage: AbsolutePath(packageRoot),
@@ -244,7 +265,7 @@ public actor SwiftPMBuildSystem {
244265
fileSystem: fileSystem,
245266
location: location,
246267
configuration: configuration,
247-
customHostToolchain: swiftPMToolchain
268+
customHostToolchain: hostSwiftPMToolchain
248269
)
249270

250271
let buildConfiguration: PackageModel.BuildConfiguration
@@ -265,20 +286,21 @@ public actor SwiftPMBuildSystem {
265286
self.toolsBuildParameters = try BuildParameters(
266287
destination: .host,
267288
dataPath: location.scratchDirectory.appending(
268-
component: swiftPMToolchain.targetTriple.platformBuildPathComponent
289+
component: hostSwiftPMToolchain.targetTriple.platformBuildPathComponent
269290
),
270291
configuration: buildConfiguration,
271-
toolchain: swiftPMToolchain,
292+
toolchain: hostSwiftPMToolchain,
272293
flags: buildFlags
273294
)
274295

275296
self.destinationBuildParameters = try BuildParameters(
276297
destination: .target,
277298
dataPath: location.scratchDirectory.appending(
278-
component: swiftPMToolchain.targetTriple.platformBuildPathComponent
299+
component: destinationSwiftPMToolchain.targetTriple.platformBuildPathComponent
279300
),
280301
configuration: buildConfiguration,
281-
toolchain: swiftPMToolchain,
302+
toolchain: destinationSwiftPMToolchain,
303+
triple: destinationSDK.targetTriple,
282304
flags: buildFlags
283305
)
284306

Tests/SourceKitLSPTests/SwiftPMIntegration.swift

+49
Original file line numberDiff line numberDiff line change
@@ -241,4 +241,53 @@ final class SwiftPMIntegrationTests: XCTestCase {
241241
]
242242
)
243243
}
244+
245+
func testWasm() async throws {
246+
let project = try await SwiftPMTestProject(
247+
files: [
248+
"/.sourcekit-lsp/config.json": """
249+
{
250+
"swiftPM": {
251+
"triple": "wasm32-unknown-none-wasm"
252+
}
253+
}
254+
""",
255+
"Test.swift": """
256+
#if arch(wasm32)
257+
let _: UnsafeRawPointer = 1
258+
#endif
259+
""",
260+
],
261+
manifest: """
262+
let package = Package(
263+
name: "WasmTest",
264+
targets: [
265+
.executableTarget(
266+
name: "wasmTest",
267+
cSettings: [.unsafeFlags(["-fdeclspec"])],
268+
swiftSettings: [
269+
.enableExperimentalFeature("Embedded"),
270+
.interoperabilityMode(.Cxx),
271+
.unsafeFlags(["-wmo", "-disable-cmo", "-Xfrontend", "-gnone"]),
272+
],
273+
linkerSettings: [.unsafeFlags(["-Xclang-linker", "-nostdlib", "-Xlinker", "--no-entry"])]
274+
)
275+
]
276+
)
277+
"""
278+
)
279+
280+
let (uri, _) = try project.openDocument("Test.swift")
281+
let diagnostics = try await project.testClient.send(
282+
DocumentDiagnosticsRequest(textDocument: TextDocumentIdentifier(uri))
283+
)
284+
guard case .full(let diagnostics) = diagnostics else {
285+
XCTFail("Expected full diagnostics report")
286+
return
287+
}
288+
XCTAssertEqual(
289+
diagnostics.items.map(\.message),
290+
["Cannot convert value of type 'Int' to specified type 'UnsafeRawPointer'"]
291+
)
292+
}
244293
}

0 commit comments

Comments
 (0)