@ondeinference / onde / commits / 547cdb3

Add script and workflow to build Swift XCFramework

Seto Elkahfi committed Mar 30, 2026 at 19:59 UTC 547cdb344c4a19991968c7c51515ab790da2241c
2 files changed +127
.github/scripts/build-swift-xcframework.sh new
+74
@@ -0,0 +1,74 @@
1 +#!/usr/bin/env bash
2 +set -euo pipefail
3 +
4 +ROOT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/../.." && pwd)
5 +cd "$ROOT_DIR"
6 +
7 +DIST_DIR="$ROOT_DIR/dist/swift"
8 +PACKAGE_DIR="$DIST_DIR/Package"
9 +HEADERS_DIR="$DIST_DIR/Headers"
10 +FRAMEWORK_DIR="$DIST_DIR/OndeFramework.xcframework"
11 +ZIP_PATH="$DIST_DIR/OndeFramework.xcframework.zip"
12 +CHECKSUM_PATH="$DIST_DIR/OndeFramework.checksum.txt"
13 +VERSION_PATH="$DIST_DIR/version.txt"
14 +BINDGEN="$ROOT_DIR/uniffi-bindgen/target/release/uniffi-bindgen"
15 +
16 +mkdir -p "$DIST_DIR" "$PACKAGE_DIR/Sources/Onde" "$HEADERS_DIR"
17 +
18 +cargo build --manifest-path uniffi-bindgen/Cargo.toml --release
19 +
20 +# Build staticlibs only. Avoid the cdylib link step; the XCFramework consumes .a slices.
21 +cargo rustc --target aarch64-apple-ios --release --lib --crate-type staticlib
22 +cargo rustc --target x86_64-apple-ios --release --lib --crate-type staticlib
23 +cargo rustc --target aarch64-apple-ios-sim --release --lib --crate-type staticlib
24 +cargo rustc --target aarch64-apple-darwin --release --lib --crate-type staticlib
25 +cargo rustc --target x86_64-apple-darwin --release --lib --crate-type staticlib
26 +cargo +nightly rustc -Z build-std --target aarch64-apple-tvos --release --lib --crate-type staticlib
27 +cargo +nightly rustc -Z build-std --target x86_64-apple-tvos --release --lib --crate-type staticlib
28 +cargo +nightly rustc -Z build-std --target aarch64-apple-tvos-sim --release --lib --crate-type staticlib
29 +
30 +"$BINDGEN" generate "$ROOT_DIR/target/aarch64-apple-ios/release/libonde.a" --language swift --out-dir "$PACKAGE_DIR/Sources/Onde"
31 +
32 +cp "$PACKAGE_DIR/Sources/Onde/ondeFFI.h" "$HEADERS_DIR/ondeFFI.h"
33 +cp "$PACKAGE_DIR/Sources/Onde/ondeFFI.modulemap" "$HEADERS_DIR/module.modulemap"
34 +
35 +lipo -create "$ROOT_DIR/target/x86_64-apple-ios/release/libonde.a" "$ROOT_DIR/target/aarch64-apple-ios-sim/release/libonde.a" -output "$DIST_DIR/libonde-ios-sim.a"
36 +
37 +lipo -create "$ROOT_DIR/target/x86_64-apple-tvos/release/libonde.a" "$ROOT_DIR/target/aarch64-apple-tvos-sim/release/libonde.a" -output "$DIST_DIR/libonde-tvos-sim.a"
38 +
39 +lipo -create "$ROOT_DIR/target/aarch64-apple-darwin/release/libonde.a" "$ROOT_DIR/target/x86_64-apple-darwin/release/libonde.a" -output "$DIST_DIR/libonde-macos.a"
40 +
41 +xcodebuild -create-xcframework -library "$ROOT_DIR/target/aarch64-apple-ios/release/libonde.a" -headers "$HEADERS_DIR" -library "$DIST_DIR/libonde-ios-sim.a" -headers "$HEADERS_DIR" -library "$ROOT_DIR/target/aarch64-apple-tvos/release/libonde.a" -headers "$HEADERS_DIR" -library "$DIST_DIR/libonde-tvos-sim.a" -headers "$HEADERS_DIR" -library "$DIST_DIR/libonde-macos.a" -headers "$HEADERS_DIR" -output "$FRAMEWORK_DIR"
42 +
43 +export FRAMEWORK_DIR ZIP_PATH
44 +python3 - <<'ZIP'
45 +import os
46 +import zipfile
47 +from pathlib import Path
48 +root = Path(os.environ['FRAMEWORK_DIR'])
49 +out = Path(os.environ['ZIP_PATH'])
50 +with zipfile.ZipFile(out, 'w', compression=zipfile.ZIP_DEFLATED, compresslevel=9) as zf:
51 + for folder, _, files in os.walk(root):
52 + for name in files:
53 + path = Path(folder) / name
54 + zf.write(path, path.relative_to(root.parent))
55 +ZIP
56 +
57 +CHECKSUM=$(swift package compute-checksum "$ZIP_PATH")
58 +printf '%s
59 +' "$CHECKSUM" > "$CHECKSUM_PATH"
60 +
61 +VERSION=$(python3 - <<'VER'
62 +from pathlib import Path
63 +import tomllib
64 +cargo = Path('Cargo.toml').read_text().encode()
65 +print(tomllib.loads(cargo.decode())['package']['version'])
66 +VER
67 +)
68 +printf '%s
69 +' "$VERSION" > "$VERSION_PATH"
70 +
71 +echo "XCFramework: $FRAMEWORK_DIR"
72 +echo "Zip: $ZIP_PATH"
73 +echo "Checksum: $CHECKSUM"
74 +echo "Version: $VERSION"
.github/workflows/build-swift-xcframework.yml new
+53
@@ -0,0 +1,53 @@
1 +name: Build Swift XCFramework
2 +
3 +on:
4 + workflow_dispatch:
5 + release:
6 + types: [published]
7 +
8 +permissions:
9 + contents: write
10 +
11 +jobs:
12 + build-swift-xcframework:
13 + runs-on: macos-15
14 + steps:
15 + - name: Checkout
16 + uses: actions/checkout@v4
17 +
18 + - name: Install stable Rust toolchain
19 + uses: dtolnay/rust-toolchain@stable
20 + with:
21 + toolchain: 1.92.0
22 + targets: aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim,aarch64-apple-darwin,x86_64-apple-darwin
23 +
24 + - name: Install nightly Rust toolchain for tvOS
25 + uses: dtolnay/rust-toolchain@nightly
26 + with:
27 + components: rust-src
28 + targets: aarch64-apple-tvos
29 +
30 + - name: Verify Xcode
31 + run: xcodebuild -version
32 +
33 + - name: Build Swift XCFramework
34 + run: .github/scripts/build-swift-xcframework.sh
35 +
36 + - name: Upload XCFramework artifacts
37 + uses: actions/upload-artifact@v4
38 + with:
39 + name: onde-swift-xcframework
40 + path: |
41 + dist/swift/OndeFramework.xcframework.zip
42 + dist/swift/OndeFramework.checksum.txt
43 + dist/swift/version.txt
44 + dist/swift/Package/Sources/Onde/onde.swift
45 + if-no-files-found: error
46 +
47 + - name: Upload release assets
48 + if: github.event_name == 'release'
49 + uses: softprops/action-gh-release@v2
50 + with:
51 + files: |
52 + dist/swift/OndeFramework.xcframework.zip
53 + dist/swift/OndeFramework.checksum.txt