Skip to content

Fix default.metallib lookup under swift test with Swift Build - #4527

Open
heckj wants to merge 1 commit into
ml-explore:mainfrom
heckj:fix/metal-swiftpm-test-bundle-lookup
Open

heckj wants to merge 1 commit into
ml-explore:mainfrom
heckj:fix/metal-swiftpm-test-bundle-lookup

Conversation

@heckj

@heckj heckj commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Summary

swift test's default build system (--build-system swiftbuild) nests resource bundles inside the .xctest and runs tests through the toolchain's swiftpm-testing-helper. The running binary is the toolchain helper, not the test bundle, so neither Bundle.main nor Bundle.allBundles names the .xctest, and the existing SwiftPM bundle search in load_swiftpm_library can never reach it. MLX aborts the entire test process on the first GPU call rather than failing one test.

fixes: ml-explore/mlx-swift#460

Reported downstream at ml-explore/mlx-swift#460, where a SwiftPM package with a test target hitting any MLX op takes down all 126 tests in the suite with:

MLX error: Failed to load the default metallib. library not found library not
found library not found library not found
  at .../Cmlx/mlx-c/mlx/c/array.cpp:232

Fix

In the Swift Build test layout, the metallib sits at a fixed offset from the binary: ../Resources/<bundle>.bundle/Contents/Resources/default.metallib. This adds that as one more colocated candidate, guarded by SWIFTPM_BUNDLE so it's a no-op for CMake/framework builds.

swift test --build-system native is unaffected -- its flat layout was already covered by the first colocated candidate -- but native is marked deprecated by SwiftPM.

Testing

Reproduced and fixed against a local project that consumes mlx-swift. I have a separate Swift package with a trait-gated target that depends on mlx-swift transitively (through mlx-swift-lm/MLXEmbedders), with its own swift-testing test target. On this machine's toolchain (Xcode 27.0, Swift 6.4.0.34.1):

  • Unpatched (mlx-swift 0.31.6): swift test --traits MLXEmbedding with MLX_RUNTIME_TESTS=1 reproduces the exact reported failure:
    MLX error: Failed to load the default metallib. library not found library not found library not found library not found  at .../Cmlx/mlx-c/mlx/c/array.cpp:232
    
  • Same command, with this patch applied: all 20 tests in that suite pass.

I also ran this against mlx-swift's own test suite (swift test --filter 'MLXTests.MLXArrayTests|MLXTests.StreamTests', 36 tests, real GPU evals) with the patch applied -- all pass, no regressions.

swift test's default build system (--build-system swiftbuild) nests
resource bundles inside the .xctest and runs tests through the
toolchain's swiftpm-testing-helper. The running binary is therefore
the toolchain helper, not the test bundle, so neither Bundle.main nor
Bundle.allBundles names the .xctest and the existing SwiftPM bundle
search can never reach it. MLX aborts the whole test process on the
first GPU call instead of failing a single test.

In that layout the metallib sits at a fixed offset from the binary
(../Resources/<bundle>.bundle/Contents/Resources/default.metallib),
so add that as an explicit colocated candidate under SWIFTPM_BUNDLE.

swift test --build-system native is unaffected (flat layout, already
covered by the first colocated candidate) but is deprecated in
SwiftPM.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MLX cannot find default.metallib under swift test with the Swift Build build system (aborts the whole test run)

1 participant