Skip to content

Remove the MPS backend from the SwiftPM package - #22182

Merged
shoumikhin merged 1 commit into
pytorch:swiftpmfrom
shoumikhin:remove-mps-swiftpm
Aug 26, 2026
Merged

Remove the MPS backend from the SwiftPM package#22182
shoumikhin merged 1 commit into
pytorch:swiftpmfrom
shoumikhin:remove-mps-swiftpm

Conversation

@shoumikhin

@shoumikhinshoumikhin commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

The MPS backend is being removed from the runtime, so this template must stop
asking for it.

The release job fills one __SHA256_<framework>__ placeholder per framework
that was actually built and uploaded. Once MPS is no longer built, nothing
substitutes __SHA256_backend_mps__, and the published manifest would carry the
literal placeholder text as a checksum plus a download URL for an archive that
was never uploaded.

That failure would be quiet and wide. The manifest still parses, so nothing
complains at generation time, and SwiftPM downloads every binary target during
resolution rather than only the ones a project uses. So every consumer of the
package would fail to resolve it, not only projects that wanted MPS.

Test Plan:
Ran the release job's substitution steps against this template using exactly the
framework list that remains after MPS is removed from the runtime build.

Before this change, two placeholders were left unsubstituted
(__SHA256_backend_mps__ and __SHA256_backend_mps_debug__), and the resulting
manifest still parsed, which is what makes the failure quiet.

After this change no placeholder is left, the generated manifest parses, and it
declares 16 products and 18 binary targets with no reference to MPS and no
unsubstituted checksum. Every wrapper target still has its matching stub
directory, and no stub directory is left orphaned.

Note on ordering: this targets the swiftpm branch and is safe to land in either
order relative to the runtime removal. If it lands first, the release job simply
substitutes a placeholder that no longer exists, which is a no-op, and the
generated manifest is still complete. Verified by running the substitution with a
checksum list that still included MPS.

Note for operators: the template branch is shared with release branches

This template branch is checked out by the Apple workflow on main and on every
release/* branch, so the change reaches more than one publishing path.

release/1.0 still builds the removed framework, still checks out this same
template, and force-pushes the result to a fixed swiftpm-1.0.0 branch that
applications can pin. Unlike main, it has no guardrail step that aborts when the
target branch already exists. So re-dispatching the Apple workflow on release/1.0
after this lands would republish swiftpm-1.0.0 with the product silently missing,
and a pinned application would fail to resolve.

Nothing is scheduled on that branch (it last moved in November 2025), so this is a
constraint to be aware of rather than an imminent break, and it needs no change
here. If a release/1.0 Apple run is ever needed again, that branch needs this
same template change first.

The MPS backend is being removed from the runtime, so this template must stop
asking for it.
The release job fills one `__SHA256_<framework>__` placeholder per framework
that was actually built and uploaded. Once MPS is no longer built, nothing
substitutes `__SHA256_backend_mps__`, and the published manifest would carry the
literal placeholder text as a checksum plus a download URL for an archive that
was never uploaded.
That failure would be quiet and wide. The manifest still parses, so nothing
complains at generation time, and SwiftPM downloads every binary target during
resolution rather than only the ones a project uses. So every consumer of the
package would fail to resolve it, not only projects that wanted MPS.
Test Plan:
Ran the release job's substitution steps against this template using exactly the
framework list that remains after MPS is removed from the runtime build.
Before this change, two placeholders were left unsubstituted
(`__SHA256_backend_mps__` and `__SHA256_backend_mps_debug__`), and the resulting
manifest still parsed, which is what makes the failure quiet.
After this change no placeholder is left, the generated manifest parses, and it
declares 16 products and 18 binary targets with no reference to MPS and no
unsubstituted checksum. Every wrapper target still has its matching stub
directory, and no stub directory is left orphaned.
@pytorch-bot

Copy link
Copy Markdown

🔗 Helpful Links

🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/22182

Note: Links to docs will display an error until the docs builds have been completed.

This comment was automatically generated by Dr. CI and updates every 15 minutes.

@meta-clameta-claBot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Aug 26, 2026
@shoumikhin

Copy link
Copy Markdown
ContributorAuthor

Companion to #22181, which removes the MPS backend from the runtime, the build
and the framework list this template's checksums come from.

@shoumikhin
shoumikhin merged commit 8b50947 into pytorch:swiftpmAug 26, 2026
8 checks passed
shoumikhin added a commit that referenced this pull request Aug 26, 2026
The MPS backend was deprecated in ExecuTorch 1.2 and its own deprecation
notices say it will be removed in 1.4. The tree is now at 1.5.0, so the
removal is overdue. Delete it.
MPS delegated model execution to Apple's MPSGraph framework. The
replacements
its deprecation notice names are still here: Core ML for general Apple
acceleration, and the Metal backend for macOS GPU work.
What goes away:
- `backends/apple/mps/` and `examples/apple/mps/`
- the `EXECUTORCH_BUILD_MPS` build option, and the places that set it
- the `backend_mps` SwiftPM product and its Apple framework build rules
- the `--mps` export flag, the `backend.mps.enabled` config key, and
`get_mps_partitioner`
- the MPS CI jobs, benchmark configurations, and documentation pages
- `EXECUTORCH_BUILD_KERNELS_TORCHAO_MPS`, which built torchao's Metal
kernels
for this runtime. Those kernels include a header from this backend and
call
into its namespace, so they cannot outlive it. The option was off by
default
and set by nothing in the tree.
Two things that look like MPS are deliberately kept, because they are
unrelated
to this backend:
- The Metal backend links Apple's MetalPerformanceShaders framework
directly for
some fallback operations. That is a system library, not this delegate.
- `TORCHAO_BUILD_EXPERIMENTAL_MPS` builds torchao's own Metal kernels
for eager
PyTorch. It never sets `TORCHAO_BUILD_EXECUTORCH_OPS`, so it does not
reach
the variant that depended on this backend.
`--device mps` in an export script is PyTorch's device name for Apple
GPUs, and
`MPS` in a codegen fixture is a PyTorch dispatch key. Both stay.
Removed documentation pages redirect to the backend overview, which
lists the
Apple alternatives, rather than returning 404.
Callers passing `-DEXECUTORCH_BUILD_MPS=ON` will find the option is
gone. CMake
reports it as an unused variable rather than failing, and the build
produces a
runtime without the backend, which is the correct end state. The `--mps`
flag of
the Apple framework script is rejected outright, since that script
validates its
arguments.
Test Plan:
No test exercises this backend after the change, so verification focused
on
proving nothing else broke.
Configured the Apple build and the LLM build to completion. Both
previously
turned this backend on by default, and both configure with it absent.
Then built
and linked the example runner: it contains no symbol from this backend,
still
registers Core ML and XNNPACK, and runs a delegated model to the correct
result.
The two source lists in the build glue are consumed positionally, so
both were
checked to still be the same length, and every list name the build asks
for was
confirmed to still resolve.
Ran the benchmark configuration logic directly: the iOS configuration
list no
longer offers this backend, one model's expected list matches, and no
disabled
entry names a configuration that no longer exists.
Parsed the changed workflow files as YAML and confirmed no job remains.
Parsed
both Xcode projects and confirmed no reference to the removed package
product
and no dangling object references. Checked the SwiftPM manifest still
has a stub
directory for every product it declares, and no orphan directories.
Built the affected documentation table with Sphinx and MyST to confirm
it still
renders as a table rather than being replaced by a parse error, which is
what a
row with the wrong number of cells causes. Confirmed every redirect
target
resolves to a real page, and that no remaining cross-reference points at
a
deleted one.
Syntax-checked the changed shell scripts, and confirmed formatting and
lint are
clean on the changed Python, CMake and HTML files.
Finally, swept the tree with a word-boundary search rather than a token
search,
and audited every remaining match. What remains is PyTorch's device
name, a
PyTorch dispatch key, torchao's eager Metal kernels, tokenizer
vocabulary
entries, Arm Corstone board names, and historical notes under `.wiki/`.
Also make the SwiftPM release step check that the manifest and the built
frameworks
describe the same set, in both directions, since each failure is silent
on its own.
A placeholder with no framework publishes literal text where a checksum
belongs:
eight consecutive nightly manifests in August 2025 shipped that way,
which makes the
package unresolvable for every consumer rather than only users of that
product. A
framework with no product is the reverse, and matters here because
release branches
share one template, so a branch that still builds a removed framework
would drop the
product from the manifest silently. Both checks run only on a publishing
run, so a
template that is momentarily out of step with a branch does not redden
unrelated
pull requests. Removing a framework is exactly the change that exercises
this, so
the guard belongs with it.
Verified the guard against the real manifests from that incident: it
fails on the
affected days, naming the surviving placeholders, and passes on the day
the
incident ended.
The guard compares each built framework against the product base name,
because the
manifest declares each product once and synthesises its debug variant in
Swift.
The SwiftPM package needs a matching change on its own branch: #22182.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA SignedThis label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@shoumikhin@metascroy