Summary
After looking at the repo more carefully: your existing release.yml already builds and uploads Cmlx.xcframework.zip to each GitHub Release. The missing piece is small — wiring that artifact to a .binaryTarget in Package.swift so SwiftPM consumers can resolve the binary instead of compiling 260 MB of C++ from source.
The gap
The existing workflow:
- ✅ Builds
Cmlx.xcframework via tools/create-xcframework.sh
- ✅ Zips and uploads to GitHub Release via
gh release upload
- ❌ Does not compute SHA256 checksum
- ❌ Does not update
Package.swift with a .binaryTarget on the release tag
Proposed addition (~30 lines to release.yml)
After the existing upload step, add:
- name: Compute Cmlx xcframework checksum
working-directory: xcode
run: |
CHECKSUM=$(swift package compute-checksum build/output/Cmlx.xcframework.zip)
echo "CMLX_CHECKSUM=$CHECKSUM" >> $GITHUB_ENV
- name: Update Package.swift binary target for this release
run: |
VERSION="${{ github.ref_name }}"
URL="https://github.com/ml-explore/mlx-swift/releases/download/${VERSION}/Cmlx.xcframework.zip"
python3 tools/update-binary-target.py \
--package Package.swift \
--name Cmlx \
--url "$URL" \
--checksum "${{ env.CMLX_CHECKSUM }}"
- name: Commit and re-tag with updated Package.swift
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add Package.swift
git commit -m "chore: set Cmlx binary target for ${{ github.ref_name }}"
git tag -f "${{ github.ref_name }}"
git push origin "${{ github.ref_name }}" --force-with-lease
git push origin --tags --force-with-lease
Plus a small Python script (tools/update-binary-target.py) that rewrites the Cmlx source target block to a .binaryTarget(...) in Package.swift.
Why main stays as source
main keeps Cmlx as a source target — the xcframework build workflow needs to compile from source. The tag-rewrite only affects the release commit, which is what SwiftPM resolves when consumers pin to a version.
Questions before opening a PR
- Is this approach acceptable? (tag-rewrite pattern is used by other packages but I want to confirm you're comfortable with it)
- Any preference on whether all 4 xcframework targets get binary targets, or just
Cmlx first?
- Your
release.yml uses [self-hosted, macos] — the swift package compute-checksum step should work fine there, but let me know if there are any toolchain constraints.
Happy to open a PR with the full implementation once there's a green light.
Summary
After looking at the repo more carefully: your existing
release.ymlalready builds and uploadsCmlx.xcframework.zipto each GitHub Release. The missing piece is small — wiring that artifact to a.binaryTargetinPackage.swiftso SwiftPM consumers can resolve the binary instead of compiling 260 MB of C++ from source.The gap
The existing workflow:
Cmlx.xcframeworkviatools/create-xcframework.shgh release uploadPackage.swiftwith a.binaryTargeton the release tagProposed addition (~30 lines to
release.yml)After the existing upload step, add:
Plus a small Python script (
tools/update-binary-target.py) that rewrites theCmlxsource target block to a.binaryTarget(...)inPackage.swift.Why main stays as source
mainkeepsCmlxas a source target — the xcframework build workflow needs to compile from source. The tag-rewrite only affects the release commit, which is what SwiftPM resolves when consumers pin to a version.Questions before opening a PR
Cmlxfirst?release.ymluses[self-hosted, macos]— theswift package compute-checksumstep should work fine there, but let me know if there are any toolchain constraints.Happy to open a PR with the full implementation once there's a green light.