From df8b74f854057356241cb629b418152633b1d90a Mon Sep 17 00:00:00 2001 From: Ben Williams Date: Mon, 17 Aug 2026 19:20:14 -0700 Subject: [PATCH 1/3] Fix macOS Swift SDK selection --- .github/workflows/ci.yml | 7 +++++++ packages/swift-node/src/compiler.ts | 18 +++++++++++++++++- packages/swift-node/test/compiler.test.ts | 12 ++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1dbd425..40b657d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -159,6 +159,13 @@ jobs: node-version: '24' cache: true + # This example imports Foundation and Security. Run it with the same + # externally selected toolchain pattern supported by swift-node. + - name: Install selected macOS Swift toolchain + uses: SwiftyLab/setup-swift@38f54a76b70d989321de9dc7c840618c08cf56e9 # v1.14.0 + with: + swift-version: 6.3.3 + - name: Verify toolchain run: | swiftc --version diff --git a/packages/swift-node/src/compiler.ts b/packages/swift-node/src/compiler.ts index f4eb5f3..c34fd22 100644 --- a/packages/swift-node/src/compiler.ts +++ b/packages/swift-node/src/compiler.ts @@ -275,9 +275,25 @@ export function swiftCompileArgs( return args } +/** + * Invoke the macOS compiler through xcrun so it receives the selected Xcode + * SDK. xcrun also honors TOOLCHAINS, which lets callers use a Swift toolchain + * installed alongside Xcode without losing access to Apple frameworks. + */ +export function swiftcInvocation( + args: string[], + platform = process.platform, +): { command: string; args: string[] } { + if (platform === 'darwin') { + return { command: 'xcrun', args: ['--sdk', 'macosx', 'swiftc', ...args] } + } + return { command: 'swiftc', args } +} + export function compileSwift(config: CompilerConfig): string { const outputFile = path.join(config.objDir, 'swift.o') - run('swiftc', swiftCompileArgs(config), config.projectDir) + const { command, args } = swiftcInvocation(swiftCompileArgs(config)) + run(command, args, config.projectDir) return outputFile } diff --git a/packages/swift-node/test/compiler.test.ts b/packages/swift-node/test/compiler.test.ts index 271712a..97a30b2 100644 --- a/packages/swift-node/test/compiler.test.ts +++ b/packages/swift-node/test/compiler.test.ts @@ -10,6 +10,7 @@ import { needsNodeGypInstall, nodeGypDevDir, swiftCompileArgs, + swiftcInvocation, } from '../src/compiler' const config = { @@ -44,6 +45,17 @@ describe('cross-platform compiler commands', () => { ) }) + it('invokes the macOS Swift compiler through xcrun with the macOS SDK', () => { + const swiftArgs = swiftCompileArgs(config, 'darwin', 'arm64') + + expect(swiftcInvocation(swiftArgs, 'darwin')).toEqual({ + command: 'xcrun', + args: ['--sdk', 'macosx', 'swiftc', ...swiftArgs], + }) + expect(swiftcInvocation(swiftArgs, 'linux')).toEqual({ command: 'swiftc', args: swiftArgs }) + expect(swiftcInvocation(swiftArgs, 'win32')).toEqual({ command: 'swiftc', args: swiftArgs }) + }) + it('uses the configured deployment target consistently on Apple Silicon', () => { expect(macosDeploymentTarget('10.15', 'arm64')).toBe('10.15') expect(macosDeploymentTarget('10.15', 'x64')).toBe('10.15') From 85499f7f026c864f2506f49af5f6b32298400f8e Mon Sep 17 00:00:00 2001 From: Ben Williams Date: Mon, 17 Aug 2026 19:35:49 -0700 Subject: [PATCH 2/3] fix: preserve explicit macOS SDK selection --- packages/swift-node/src/compiler.ts | 11 ++++++++--- packages/swift-node/test/compiler.test.ts | 8 ++++++-- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/packages/swift-node/src/compiler.ts b/packages/swift-node/src/compiler.ts index c34fd22..de7835f 100644 --- a/packages/swift-node/src/compiler.ts +++ b/packages/swift-node/src/compiler.ts @@ -276,16 +276,21 @@ export function swiftCompileArgs( } /** - * Invoke the macOS compiler through xcrun so it receives the selected Xcode - * SDK. xcrun also honors TOOLCHAINS, which lets callers use a Swift toolchain + * Invoke the macOS compiler through xcrun so it receives an Xcode SDK. + * Preserve an explicit SDKROOT; otherwise select the default macOS SDK. + * xcrun also honors TOOLCHAINS, which lets callers use a Swift toolchain * installed alongside Xcode without losing access to Apple frameworks. */ export function swiftcInvocation( args: string[], platform = process.platform, + sdkRoot = process.env.SDKROOT, ): { command: string; args: string[] } { if (platform === 'darwin') { - return { command: 'xcrun', args: ['--sdk', 'macosx', 'swiftc', ...args] } + return { + command: 'xcrun', + args: [...(sdkRoot ? [] : ['--sdk', 'macosx']), 'swiftc', ...args], + } } return { command: 'swiftc', args } } diff --git a/packages/swift-node/test/compiler.test.ts b/packages/swift-node/test/compiler.test.ts index 97a30b2..3544f61 100644 --- a/packages/swift-node/test/compiler.test.ts +++ b/packages/swift-node/test/compiler.test.ts @@ -45,13 +45,17 @@ describe('cross-platform compiler commands', () => { ) }) - it('invokes the macOS Swift compiler through xcrun with the macOS SDK', () => { + it('uses xcrun for macOS Swift while preserving an explicit SDK selection', () => { const swiftArgs = swiftCompileArgs(config, 'darwin', 'arm64') - expect(swiftcInvocation(swiftArgs, 'darwin')).toEqual({ + expect(swiftcInvocation(swiftArgs, 'darwin', '')).toEqual({ command: 'xcrun', args: ['--sdk', 'macosx', 'swiftc', ...swiftArgs], }) + expect(swiftcInvocation(swiftArgs, 'darwin', '/custom/MacOSX.sdk')).toEqual({ + command: 'xcrun', + args: ['swiftc', ...swiftArgs], + }) expect(swiftcInvocation(swiftArgs, 'linux')).toEqual({ command: 'swiftc', args: swiftArgs }) expect(swiftcInvocation(swiftArgs, 'win32')).toEqual({ command: 'swiftc', args: swiftArgs }) }) From 5a51e87b454c63fa6edc07fe3c8a7385a9b144fc Mon Sep 17 00:00:00 2001 From: Ben Williams Date: Mon, 17 Aug 2026 19:41:32 -0700 Subject: [PATCH 3/3] release: bump packages to 0.3.0 --- packages/swift-node-unplugin/package.json | 4 ++-- packages/swift-node/package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/swift-node-unplugin/package.json b/packages/swift-node-unplugin/package.json index d1f3ee3..c3a01c8 100644 --- a/packages/swift-node-unplugin/package.json +++ b/packages/swift-node-unplugin/package.json @@ -1,6 +1,6 @@ { "name": "swift-node-unplugin", - "version": "0.2.0", + "version": "0.3.0", "description": "Unplugin adapters that build and bundle Swift Node native assets.", "type": "module", "types": "./dist/index.d.ts", @@ -102,7 +102,7 @@ "test": "vp test run" }, "peerDependencies": { - "swift-node": "^0.2.0" + "swift-node": "^0.3.0" }, "dependencies": { "unplugin": "3.3.0" diff --git a/packages/swift-node/package.json b/packages/swift-node/package.json index db56b8d..4c7666e 100644 --- a/packages/swift-node/package.json +++ b/packages/swift-node/package.json @@ -1,6 +1,6 @@ { "name": "swift-node", - "version": "0.2.0", + "version": "0.3.0", "type": "module", "description": "Node-API bridge for Swift. Write Node native addons in Swift without C++ glue.", "bin": {