Skip to content

Cannot use Metal properly with Swift Packages — even with Apple-recommended plugin workaround #8930

Open
@schwa

Description

@schwa

Is it reproducible with SwiftPM command-line tools: swift build, swift test, swift package etc?

  • Confirmed reproduction steps with SwiftPM CLI. The description text must include reproduction steps with either of command-line SwiftPM commands, swift build, swift test, swift package etc.

Description

Using Metal shaders from within Swift Packages remains unsupported in any meaningful way. There is no way to configure the Metal compiler: no ability to pass flags, enable debug info, control optimization, or perform logging.

Apple’s own technote (TN3133) suggests using a Swift Package build plugin to work around these limitations. I have implemented such a plugin: https://github.com/schwa/MetalCompilerPlugin (as a side note it's somewhat ridiculous that Swift Package Manager cannot adequately compile Metal source - and I've filed feedback on that 3 years ago. Provide flags to configure metal compilation · Issue #5823 · swiftlang/swift-package-manager / rdar://79153205 )

However, as of the latest Xcode 26 family, this approach is now broken as well. The metal tool requires a separate component download, and attempting to invoke it from within the plugin sandbox results in failure — even if the toolchain is already installed.

When running the MetalCompilerPlugin it fails with:

CustomTask metal 6d34921d6512f8140488dca318210815 (in target 'MetalCompilerPlugin_ExampleShaders' from project 'MetalCompilerPlugin')
    cd /Users/schwa/Shared/Projects/MetalCompilerPlugin
    /usr/bin/sandbox-exec -p \(version\ 1\)'
'\(deny\ default\)'
'\(import\ \"system.sb\"\)'
'\(allow\ file-read\*\)'
'\(allow\ process\*\)'
'\(allow\ mach-lookup\ \(global-name\ \"com.apple.lsd.mapdb\"\)\)'
'\(allow\ file-write\*'
'\ \ \ \ \(subpath\ \"/private/tmp\"\)'
'\ \ \ \ \(subpath\ \"/private/var/folders/pr/yb6s1f5n66l736cnh8vfygzm0000gn/T\"\)'
'\)'
'\(deny\ file-write\*'
'\ \ \ \ \(subpath\ \"/Users/schwa/Shared/Projects/MetalCompilerPlugin\"\)'
'\)'
'\(allow\ file-write\*'
'\ \ \ \ \(subpath\ \"/Users/schwa/Library/Developer/Xcode/DerivedData/MetalCompilerPlugin-dbmhlvzupehblxczlpulkjowpxxd/Build/Intermediates.noindex/BuildToolPluginIntermediates/metalcompilerplugin.output/ExampleShaders/MetalCompilerPlugin\"\)'
'\ \ \ \ \(subpath\ \"/private/var/folders/pr/yb6s1f5n66l736cnh8vfygzm0000gn/T/TemporaryItems\"\)'
'\)'
' /usr/bin/xcrun metal -gline-tables-only -frecord-sources -fmodules-cache-path\=/Users/schwa/Library/Developer/Xcode/DerivedData/MetalCompilerPlugin-dbmhlvzupehblxczlpulkjowpxxd/Build/Intermediates.noindex/BuildToolPluginIntermediates/metalcompilerplugin.output/ExampleShaders/MetalCompilerPlugin/cache /Users/schwa/Shared/Projects/MetalCompilerPlugin/Sources/ExampleShaders/ExampleShaders.metal -o /Users/schwa/Library/Developer/Xcode/DerivedData/MetalCompilerPlugin-dbmhlvzupehblxczlpulkjowpxxd/Build/Intermediates.noindex/BuildToolPluginIntermediates/metalcompilerplugin.output/ExampleShaders/MetalCompilerPlugin/debug.metallib

error: error: cannot execute tool 'metal' due to missing Metal Toolchain; use: xcodebuild -downloadComponent MetalToolchain

Running the suggested xcodebuild -downloadComponent MetalToolchain has no effect. The plugin continues to fail with the same error. This means there is now no supported way to compile Metal shaders from Swift Packages, even using the recommended plugin approach.

It seems that the sandboxing intrinsic to Swift Package build plugins is perhaps preventing this from working.

Changing the plugin to call xcodebuild -showComponent MetalToolchain to try and get the default path to the metal tool also fails with:

2025-07-12 08:31:08.430 xcodebuild[24545:5610274] IDEDownloadableMetalToolchainCoordinator: Error persisting Xcode-to-MetalToolchain mappings: Error Domain=NSCocoaErrorDomain Code=513 "You don’t have permission to save the file “XcodeToMetalToolchainIndexMapping.plist” in the folder “Xcode”." UserInfo={NSFilePath=/Users/schwa/Library/Developer/Xcode/XcodeToMetalToolchainIndexMapping.plist, NSURL=file:///Users/schwa/Library/Developer/Xcode/XcodeToMetalToolchainIndexMapping.plist, NSUnderlyingError=0xa13defed0 {Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted"}}
2025-07-12 08:31:08.431 xcodebuild[24545:5610269] Writing error result bundle to /var/folders/pr/yb6s1f5n66l736cnh8vfygzm0000gn/T/ResultBundle_2025-12-07_08-31-0008.xcresult

I've been testing every build of Xcode 26 since the first beta, and this issue has persisted through all of them.

Summary:

  • SwiftPM integration with Metal lacks essential compiler configuration features.
  • The recommended workaround (build plugins) no longer works due to sandbox/toolchain issues.
  • There is no remaining supported or documented path for compiling Metal shaders within Swift Packages.

Please consider improving Swift Package support for Metal — or at minimum, ensure the plugin-based workaround continues to function reliably.

Expected behavior

I expect to be able to compile Metal from SwiftPM using whatever flags I want… failing that I expect the build plugin to work with Metal

Actual behavior

Nothing works in Xcode 26 requiring that I stop using Swift Packages or the ability to debug Metal

Steps to reproduce

See description

Swift Package Manager version/commit hash

No response

Swift & OS version (output of swift --version ; uname -a)

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions