swift test aborts: default metallib unresolvable when mainBundle is the SwiftPM test runner
Setup: macOS (Apple Silicon), SwiftPM package depending on mlx-swift, tests written with swift-testing, run via swift test. Any MLX call that touches the Metal backend aborts the test process:
MLX error: Failed to load the default metallib. library not found library not found library not found library not found
swift run executables in the same package work fine.
Root cause (traced through mlx/backend/metal/device.cpp)
load_default_library tries, in order: colocated mlx.metallib, colocated Resources/mlx, SwiftPM bundle via mainBundle + allBundles + frameworks, colocated Resources/default, then METAL_PATH ("default.metallib", CWD-relative).
I printed Bundle.main.bundleURL and Bundle.allBundles from inside the test process:
MAIN: /Applications/Xcode.app/.../usr/libexec/swift/pm
BUNDLE: /Applications/Xcode.app/.../usr/libexec/swift/pm (only entry)
Under swift test, mainBundle is the SwiftPM test runner inside the toolchain, not the .xctest bundle — and allBundles contains only the runner. So attempt 3 can never find mlx-swift_Cmlx.bundle even though it exists at LayaKitTests.xctest/Contents/Resources/mlx-swift_Cmlx.bundle/Contents/Resources/default.metallib (verified on disk). Attempts 1/2/4 miss (no colocated files), and attempt 5 misses (repo root has no default.metallib). Net: 4× "library not found", abort.
(With classic XCTest the .xctest binary likely execs directly so allBundles might save it; with the swift-testing runner flow it cannot work.)
Suggested fixes (any one unblocks swift test)
- Honor an env override, e.g.
MLX_METAL_PATH, checked before the bundle search. Test targets could then point at the built resource, and apps with custom layouts get an escape hatch.
- In
load_swiftpm_library, additionally probe each bundle's resourceURL and bundleURL/Contents/Resources explicitly rather than relying on allBundles containing the host — though while mainBundle is the toolchain runner this still misses unless the .xctest is enumerated.
- Document that Metal-backed tests are unsupported under
swift test if neither is planned.
Repro
Any package with mlx-swift + a swift-testing test that evaluates an MLXArray (e.g. eval(a + b)), run with swift test on Apple Silicon. Happy to provide a minimal repo if useful.
Environment: macOS 27.2 arm64, Xcode-beta toolchain, mlx-swift 0.31.6+, Python-free pure-Swift package.
swift testaborts: default metallib unresolvable when mainBundle is the SwiftPM test runnerSetup: macOS (Apple Silicon), SwiftPM package depending on
mlx-swift, tests written withswift-testing, run viaswift test. Any MLX call that touches the Metal backend aborts the test process:swift runexecutables in the same package work fine.Root cause (traced through
mlx/backend/metal/device.cpp)load_default_librarytries, in order: colocatedmlx.metallib, colocatedResources/mlx, SwiftPM bundle viamainBundle+allBundles+ frameworks, colocatedResources/default, thenMETAL_PATH("default.metallib", CWD-relative).I printed
Bundle.main.bundleURLandBundle.allBundlesfrom inside the test process:Under
swift test,mainBundleis the SwiftPM test runner inside the toolchain, not the.xctestbundle — andallBundlescontains only the runner. So attempt 3 can never findmlx-swift_Cmlx.bundleeven though it exists atLayaKitTests.xctest/Contents/Resources/mlx-swift_Cmlx.bundle/Contents/Resources/default.metallib(verified on disk). Attempts 1/2/4 miss (no colocated files), and attempt 5 misses (repo root has nodefault.metallib). Net: 4× "library not found", abort.(With classic XCTest the
.xctestbinary likely execs directly soallBundlesmight save it; with the swift-testing runner flow it cannot work.)Suggested fixes (any one unblocks
swift test)MLX_METAL_PATH, checked before the bundle search. Test targets could then point at the built resource, and apps with custom layouts get an escape hatch.load_swiftpm_library, additionally probe each bundle'sresourceURLandbundleURL/Contents/Resourcesexplicitly rather than relying onallBundlescontaining the host — though whilemainBundleis the toolchain runner this still misses unless the.xctestis enumerated.swift testif neither is planned.Repro
Any package with
mlx-swift+ aswift-testingtest that evaluates anMLXArray(e.g.eval(a + b)), run withswift teston Apple Silicon. Happy to provide a minimal repo if useful.Environment: macOS 27.2 arm64, Xcode-beta toolchain, mlx-swift 0.31.6+, Python-free pure-Swift package.