diff --git a/package.json b/package.json index 54f7e7936..bb8dd2b81 100644 --- a/package.json +++ b/package.json @@ -599,9 +599,15 @@ "swift.SDK": { "type": "string", "default": "", - "markdownDescription": "The path of the SDK to compile against (`--sdk` parameter). This is of use when supporting non-standard SDK layouts on Windows and using custom SDKs. The default SDK is determined by the environment on macOS and Windows.", + "markdownDescription": "The path of the SDK to compile against (`--sdk` parameter). This is of use when supporting non-standard SDK layouts on Windows and using custom SDKs. The default SDK is determined by the environment on macOS and Windows.\n\nFor SwiftPM projects, prefer using `swift.swiftSDK` with a triple (such as `arm64-apple-ios`) or Swift SDK name instead.", "order": 3 }, + "swift.swiftSDK": { + "type": "string", + "default": "", + "markdownDescription": "The [Swift SDK](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0387-cross-compilation-destinations.md) to compile against (`--swift-sdk` parameter).", + "order": 4 + }, "swift.diagnostics": { "type": "boolean", "default": false, diff --git a/src/configuration.ts b/src/configuration.ts index 5741e4a74..5422eeda1 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -190,13 +190,20 @@ const configuration = { get runtimePath(): string { return vscode.workspace.getConfiguration("swift").get("runtimePath", ""); }, - /** Path to custom swift sdk */ + /** Path to custom --sdk */ get sdk(): string { return vscode.workspace.getConfiguration("swift").get("SDK", ""); }, set sdk(value: string | undefined) { vscode.workspace.getConfiguration("swift").update("SDK", value); }, + /** Path to custom --swift-sdk */ + get swiftSDK(): string { + return vscode.workspace.getConfiguration("swift").get("swiftSDK", ""); + }, + set swiftSDK(value: string | undefined) { + vscode.workspace.getConfiguration("swift").update("swiftSDK", value); + }, /** swift build arguments */ get buildArguments(): string[] { return vscode.workspace.getConfiguration("swift").get("buildArguments", []); diff --git a/src/extension.ts b/src/extension.ts index f2dc998c2..6a395496d 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -98,7 +98,10 @@ export async function activate(context: vscode.ExtensionContext): Promise { ); } // on sdk config change, restart sourcekit-lsp - if (event.affectsConfiguration("swift.SDK")) { + if ( + event.affectsConfiguration("swift.SDK") || + event.affectsConfiguration("swift.swiftSDK") + ) { // FIXME: There is a bug stopping us from restarting SourceKit-LSP directly. // As long as it's fixed we won't need to reload on newer versions. showReloadExtensionNotification( diff --git a/src/sourcekit-lsp/LanguageClientManager.ts b/src/sourcekit-lsp/LanguageClientManager.ts index e6f624dc4..579783f70 100644 --- a/src/sourcekit-lsp/LanguageClientManager.ts +++ b/src/sourcekit-lsp/LanguageClientManager.ts @@ -641,6 +641,14 @@ export class LanguageClientManager implements vscode.Disposable { backgroundPreparationMode: "enabled", }; } + + if (configuration.swiftSDK !== "") { + options = { + ...options, + swiftPM: { swiftSDK: configuration.swiftSDK }, + }; + } + return options; } diff --git a/src/toolchain/BuildFlags.ts b/src/toolchain/BuildFlags.ts index 7b06ff6a2..182d72a98 100644 --- a/src/toolchain/BuildFlags.ts +++ b/src/toolchain/BuildFlags.ts @@ -73,10 +73,14 @@ export class BuildFlags { * Get SDK flags for SwiftPM */ swiftpmSDKFlags(): string[] { + const flags: string[] = []; if (configuration.sdk !== "") { - return ["--sdk", configuration.sdk, ...this.swiftDriverTargetFlags(true)]; + flags.push("--sdk", configuration.sdk, ...this.swiftDriverTargetFlags(true)); } - return []; + if (configuration.swiftSDK !== "") { + flags.push("--swift-sdk", configuration.swiftSDK); + } + return flags; } /** diff --git a/test/unit-tests/sourcekit-lsp/LanguageClientManager.test.ts b/test/unit-tests/sourcekit-lsp/LanguageClientManager.test.ts index d82e76bc9..ca322c8db 100644 --- a/test/unit-tests/sourcekit-lsp/LanguageClientManager.test.ts +++ b/test/unit-tests/sourcekit-lsp/LanguageClientManager.test.ts @@ -187,6 +187,25 @@ suite("LanguageClientManager Suite", () => { expect(languageClientMock.start).to.have.been.calledOnce; }); + test("launches SourceKit-LSP on startup with swiftSDK", async () => { + mockedConfig.swiftSDK = "arm64-apple-ios"; + + const sut = new LanguageClientManager(instance(mockedWorkspace), languageClientFactoryMock); + await waitForReturnedPromises(languageClientMock.start); + + expect(sut.state).to.equal(State.Running); + expect(languageClientFactoryMock.createLanguageClient).to.have.been.calledOnceWith( + /* id */ match.string, + /* name */ match.string, + /* serverOptions */ match.has("command", "/path/to/toolchain/bin/sourcekit-lsp"), + /* clientOptions */ match.hasNested( + "initializationOptions.swiftPM.swiftSDK", + "arm64-apple-ios" + ) + ); + expect(languageClientMock.start).to.have.been.calledOnce; + }); + test("chooses the correct backgroundIndexing value is auto, swift version if 6.0.0", async () => { mockedWorkspace.swiftVersion = new Version(6, 0, 0); mockedConfig.backgroundIndexing = "auto"; diff --git a/test/unit-tests/toolchain/BuildFlags.test.ts b/test/unit-tests/toolchain/BuildFlags.test.ts index 0c1979546..aba7b7f40 100644 --- a/test/unit-tests/toolchain/BuildFlags.test.ts +++ b/test/unit-tests/toolchain/BuildFlags.test.ts @@ -78,9 +78,11 @@ suite("BuildFlags Test Suite", () => { suite("swiftpmSDKFlags", () => { const sdkConfig = mockGlobalValue(configuration, "sdk"); + const swiftSDKConfig = mockGlobalValue(configuration, "swiftSDK"); test("no configuration provided", async () => { sdkConfig.setValue(""); + swiftSDKConfig.setValue(""); expect(buildFlags.swiftpmSDKFlags()).to.be.an("array").that.is.empty; }); @@ -92,6 +94,22 @@ suite("BuildFlags Test Suite", () => { ]); }); + test("configuration provided for swiftSDK", () => { + swiftSDKConfig.setValue("arm64-apple-ios"); + expect(buildFlags.swiftpmSDKFlags()).to.deep.equal(["--swift-sdk", "arm64-apple-ios"]); + }); + + test("configuration provided for swiftSDK and sdk", () => { + sdkConfig.setValue("/some/other/full/test/path"); + swiftSDKConfig.setValue("arm64-apple-ios"); + expect(buildFlags.swiftpmSDKFlags()).to.deep.equal([ + "--sdk", + "/some/other/full/test/path", + "--swift-sdk", + "arm64-apple-ios", + ]); + }); + test("include target", () => { sdkConfig.setValue("/some/other/full/test/path/WatchOS.sdk"); expect(buildFlags.swiftpmSDKFlags()).to.deep.equal([