Skip to content

Commit faa05ea

Browse files
apocryphxclaude
andcommitted
xcframework: CI, rolling release, arm64-only simulators, docs
Follow-up polish on the fork's Apple-platform build: 1. CI workflow (.github/workflows/fork-xcframework-release.yml) Rebuilds the xcframework on push to master, weekly, and on-demand. Uploads a zip as a 30-day Actions artifact and publishes to a rolling "latest" prerelease so downstream consumers can curl a prebuilt framework without cloning the repo. 2. Drop x86_64 from iOS/visionOS/tvOS simulator slices Every modern Xcode Simulator runs arm64-on-arm64 on Apple Silicon. The x86_64 sim slice was dead weight — halves simulator build times and binary size. macOS keeps the Intel slice since real Intel Macs are still in use. Slice names change from e.g. "ios-arm64_x86_64-simulator" to "ios-arm64-simulator". 3. README: codesigning section Documents that the xcframework ships unsigned on purpose and that consumers must set "Embed & Sign" in Xcode. Prevents the common mistake of pre-signing before embedding, which archive validation rejects. 4. README: prebuilt download section Points consumers at the rolling "latest" release from (1) instead of making them build from source. 5. .gitignore: /.claude/ Prevents accidental commits of Claude Code workspace state. Sanity-verified locally by reconfiguring and building the arm64-only iOS simulator slice — libllama.a / libggml-metal.a produced as non-fat arm64 archives. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent f62eb3c commit faa05ea

4 files changed

Lines changed: 151 additions & 10 deletions

File tree

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
name: Fork — xcframework build & rolling release
2+
3+
# Fork-specific workflow for apocryphx/llama.cpp. Builds the Apple
4+
# xcframework using the Ninja-patched build-xcframework.sh and publishes
5+
# it to the rolling "latest" prerelease so downstream consumers can curl
6+
# a prebuilt zip.
7+
#
8+
# Separate from upstream's build-apple.yml so upstream syncs don't
9+
# clobber it. See README.md § "Downloading a prebuilt xcframework".
10+
11+
on:
12+
workflow_dispatch:
13+
push:
14+
branches: [master]
15+
paths:
16+
- 'build-xcframework.sh'
17+
- 'CMakeLists.txt'
18+
- 'ggml/**'
19+
- 'src/**'
20+
- 'include/**'
21+
- 'common/**'
22+
- '.github/workflows/fork-xcframework-release.yml'
23+
schedule:
24+
# Weekly rebuild so the "latest" asset doesn't go stale against
25+
# upstream security/bugfix releases.
26+
- cron: '17 7 * * 1'
27+
28+
concurrency:
29+
group: fork-xcframework-release
30+
cancel-in-progress: true
31+
32+
permissions:
33+
contents: write
34+
35+
jobs:
36+
build:
37+
runs-on: macos-latest
38+
timeout-minutes: 60
39+
40+
steps:
41+
- name: Checkout
42+
uses: actions/checkout@v6
43+
44+
- name: Setup Xcode
45+
uses: ggml-org/setup-xcode@v1
46+
with:
47+
xcode-version: latest-stable
48+
49+
- name: Install Ninja + ensure CMake 4.x
50+
run: |
51+
brew install ninja
52+
brew upgrade cmake || brew install cmake
53+
cmake --version
54+
ninja --version
55+
xcodebuild -version
56+
57+
- name: Build xcframework
58+
run: |
59+
./build-xcframework.sh
60+
61+
- name: Capture build metadata
62+
id: meta
63+
run: |
64+
set -e
65+
UPSTREAM_TAG=$(git describe --tags --abbrev=0 --match 'b*' 2>/dev/null || echo "unknown")
66+
COMMIT_SHORT=$(git rev-parse --short HEAD)
67+
BUILD_DATE=$(date -u +%Y-%m-%d)
68+
{
69+
echo "upstream_tag=$UPSTREAM_TAG"
70+
echo "commit_short=$COMMIT_SHORT"
71+
echo "build_date=$BUILD_DATE"
72+
} >> "$GITHUB_OUTPUT"
73+
74+
- name: Zip xcframework
75+
run: |
76+
cd build-apple
77+
zip -r -y ../llama.xcframework.zip llama.xcframework
78+
cd ..
79+
ls -lh llama.xcframework.zip
80+
shasum -a 256 llama.xcframework.zip | tee llama.xcframework.zip.sha256
81+
82+
- name: Upload workflow artifact
83+
uses: actions/upload-artifact@v6
84+
with:
85+
name: llama-xcframework-${{ steps.meta.outputs.commit_short }}
86+
path: |
87+
llama.xcframework.zip
88+
llama.xcframework.zip.sha256
89+
retention-days: 30
90+
91+
- name: Publish rolling "latest" prerelease
92+
if: github.event_name != 'pull_request'
93+
uses: softprops/action-gh-release@v2
94+
with:
95+
tag_name: latest
96+
name: "Rolling build (${{ steps.meta.outputs.build_date }})"
97+
body: |
98+
Automatically rebuilt xcframework on every push to `master` and weekly.
99+
100+
- upstream tag: `${{ steps.meta.outputs.upstream_tag }}`
101+
- fork commit: `${{ steps.meta.outputs.commit_short }}`
102+
- built: ${{ steps.meta.outputs.build_date }}
103+
- slices: ios-arm64, ios-arm64-simulator, macos-arm64_x86_64, xros-arm64, xros-arm64-simulator, tvos-arm64, tvos-arm64-simulator
104+
105+
```
106+
curl -LO https://github.com/${{ github.repository }}/releases/download/latest/llama.xcframework.zip
107+
unzip llama.xcframework.zip
108+
```
109+
110+
SHA-256: see `llama.xcframework.zip.sha256`.
111+
prerelease: true
112+
make_latest: false
113+
files: |
114+
llama.xcframework.zip
115+
llama.xcframework.zip.sha256

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,5 +143,6 @@ poetry.toml
143143
# IDE
144144
/*.code-workspace
145145
/.windsurf/
146+
/.claude/
146147
# emscripten
147148
a.out.*

README.md

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,17 @@ CMake Error at ggml/src/ggml-cpu/CMakeLists.txt:57 (target_compile_features):
2626

2727
The failure reproduces against `upstream/master`, verified 2026-04-15. Ninja bypasses it entirely because it does not rely on Xcode's toolchain detection for cross-SDK builds. The resulting xcframework is equivalent — the Xcode-specific `-DCMAKE_XCODE_ATTRIBUTE_*` arguments in `COMMON_CMAKE_ARGS` are harmless no-ops under Ninja, so they were left alone rather than stripped.
2828

29+
## Downloading a prebuilt xcframework
30+
31+
GitHub Actions rebuilds the xcframework on every push to `master` and on a weekly schedule. The latest artifact is attached to a rolling prerelease tagged `latest`:
32+
33+
```bash
34+
curl -LO https://github.com/apocryphx/llama.cpp/releases/download/latest/llama.xcframework.zip
35+
unzip llama.xcframework.zip
36+
```
37+
38+
Drag `llama.xcframework` into your Xcode project's *Frameworks, Libraries, and Embedded Content* section. Each workflow run also uploads the zip as a 30-day Actions artifact if you need a specific build.
39+
2940
## Building the xcframework
3041

3142
```bash
@@ -37,12 +48,14 @@ Output: `build-apple/llama.xcframework/` containing 7 slices:
3748
| Slice | Architectures |
3849
|---|---|
3950
| `ios-arm64` | arm64 |
40-
| `ios-arm64_x86_64-simulator` | arm64, x86_64 |
51+
| `ios-arm64-simulator` | arm64 |
4152
| `macos-arm64_x86_64` | arm64, x86_64 |
4253
| `xros-arm64` | arm64 |
43-
| `xros-arm64_x86_64-simulator` | arm64, x86_64 |
54+
| `xros-arm64-simulator` | arm64 |
4455
| `tvos-arm64` | arm64 |
45-
| `tvos-arm64_x86_64-simulator` | arm64, x86_64 |
56+
| `tvos-arm64-simulator` | arm64 |
57+
58+
Simulator slices are **arm64-only** — every modern Xcode Simulator runs arm64-on-arm64 on Apple Silicon. The x86_64 simulator slice has been dropped to halve simulator build times and binary sizes. macOS keeps the Intel slice since real Intel Macs are still in use.
4659

4760
Mac Catalyst is **not** in the xcframework — CMake's cross-compile flags conflict when combining both Catalyst architectures in a single configure step. See [APPLE-PLATFORMS-BUILD.md](APPLE-PLATFORMS-BUILD.md) for the manual lipo workflow.
4861

@@ -64,7 +77,7 @@ CMake Warning at ggml/src/ggml-cpu/CMakeLists.txt:558 (message):
6477
Unknown CPU architecture. Falling back to generic implementations.
6578
```
6679

67-
This is **not** a Metal fallback. It fires only when x86_64 is part of the architecture list (iOS sim, macOS, visionOS sim, tvOS sim) and means the x86_64 **CPU backend** slice uses generic scalar kernels instead of AVX/AVX2. The arm64 CPU backend and the Metal backend are unaffected. For shipping on Apple Silicon devices this warning is cosmetic — no one runs production inference on an x86_64 simulator.
80+
This is **not** a Metal fallback. It fires only when x86_64 is part of the architecture list (now just the `macos-arm64_x86_64` slice) and means the x86_64 **CPU backend** slice uses generic scalar kernels instead of AVX/AVX2. The arm64 CPU backend and the Metal backend are unaffected. For shipping on Apple Silicon devices this warning is cosmetic.
6881

6982
### Requirements
7083

@@ -100,6 +113,18 @@ Reference numbers from the 2026-04-15 verification (SmolLM2-135M-Instruct Q4_K_M
100113

101114
The xcframework slices contain identical Metal backend code — same `_ggml_metallib_start`/`_end` symbols, same 110 kernels — so a working host Metal build is a reliable proxy for the framework slices.
102115

116+
## Code signing
117+
118+
**The xcframework is unsigned.** `build-xcframework.sh` sets `CODE_SIGNING_ALLOWED=NO` on purpose — a redistributable framework must not carry its own signature, because the consuming app has to re-sign embedded binaries with its own Team ID at archive time. This is the expected pattern for distributing a third-party `.xcframework`.
119+
120+
When you embed `llama.xcframework` in an Xcode project:
121+
122+
- In the *Frameworks, Libraries, and Embedded Content* section, set *Embed* to **Embed & Sign**. Xcode will sign the embedded `llama.framework` with your app's signing identity during the build.
123+
- No action needed in your entitlements — the framework uses only public `Metal.framework` / `Accelerate.framework` APIs.
124+
- For distribution outside the App Store (Developer ID / notarization), the framework will be signed and notarized as part of your app's archive, not separately.
125+
126+
If Xcode refuses to build with a signature error, the fix is almost always switching *Embed* from *Do Not Embed* to *Embed & Sign*. Do **not** pre-sign the framework with `codesign` before embedding — that produces nested signatures that archive validation rejects.
127+
103128
## Syncing with upstream
104129

105130
```bash

build-xcframework.sh

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ combine_static_libraries() {
270270
"ios")
271271
if [[ "$is_simulator" == "true" ]]; then
272272
sdk="iphonesimulator"
273-
archs="arm64 x86_64"
273+
archs="arm64"
274274
min_version_flag="-mios-simulator-version-min=${IOS_MIN_OS_VERSION}"
275275
else
276276
sdk="iphoneos"
@@ -288,7 +288,7 @@ combine_static_libraries() {
288288
"visionos")
289289
if [[ "$is_simulator" == "true" ]]; then
290290
sdk="xrsimulator"
291-
archs="arm64 x86_64"
291+
archs="arm64"
292292
min_version_flag="-mtargetos=xros${VISIONOS_MIN_OS_VERSION}-simulator"
293293
else
294294
sdk="xros"
@@ -301,7 +301,7 @@ combine_static_libraries() {
301301
"tvos")
302302
if [[ "$is_simulator" == "true" ]]; then
303303
sdk="appletvsimulator"
304-
archs="arm64 x86_64"
304+
archs="arm64"
305305
min_version_flag="-mtvos-simulator-version-min=${TVOS_MIN_OS_VERSION}"
306306
else
307307
sdk="appletvos"
@@ -408,7 +408,7 @@ cmake -B build-ios-sim -G Ninja \
408408
-DIOS=ON \
409409
-DCMAKE_SYSTEM_NAME=iOS \
410410
-DCMAKE_OSX_SYSROOT=iphonesimulator \
411-
-DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" \
411+
-DCMAKE_OSX_ARCHITECTURES="arm64" \
412412
-DCMAKE_XCODE_ATTRIBUTE_SUPPORTED_PLATFORMS=iphonesimulator \
413413
-DCMAKE_C_FLAGS="${COMMON_C_FLAGS}" \
414414
-DCMAKE_CXX_FLAGS="${COMMON_CXX_FLAGS}" \
@@ -460,7 +460,7 @@ echo "Building for visionOS simulator..."
460460
cmake -B build-visionos-sim -G Ninja \
461461
"${COMMON_CMAKE_ARGS[@]}" \
462462
-DCMAKE_OSX_DEPLOYMENT_TARGET=${VISIONOS_MIN_OS_VERSION} \
463-
-DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" \
463+
-DCMAKE_OSX_ARCHITECTURES="arm64" \
464464
-DCMAKE_SYSTEM_NAME=visionOS \
465465
-DCMAKE_OSX_SYSROOT=xrsimulator \
466466
-DCMAKE_XCODE_ATTRIBUTE_SUPPORTED_PLATFORMS=xrsimulator \
@@ -478,7 +478,7 @@ cmake -B build-tvos-sim -G Ninja \
478478
-DCMAKE_OSX_DEPLOYMENT_TARGET=${TVOS_MIN_OS_VERSION} \
479479
-DCMAKE_SYSTEM_NAME=tvOS \
480480
-DCMAKE_OSX_SYSROOT=appletvsimulator \
481-
-DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" \
481+
-DCMAKE_OSX_ARCHITECTURES="arm64" \
482482
-DGGML_METAL=ON \
483483
-DCMAKE_XCODE_ATTRIBUTE_SUPPORTED_PLATFORMS=appletvsimulator \
484484
-DCMAKE_C_FLAGS="${COMMON_C_FLAGS}" \

0 commit comments

Comments
 (0)