Skip to content

Commit e7474d2

Browse files
committed
Add cdylib publishing CI and release-mode Dart build hook
Release/multi-platform delivery for the Dart package: - uniffi-cdylib.yml builds liblivekit_uniffi for desktop + mobile targets and attaches build-<triple>.zip (+ .sha256) to the livekit-uniffi release; wired into uniffi-packages.yml. Validated across all 10 targets via CI dry-run. - hook/build.dart.tera gains a download mode: fetches and SHA-256-verifies the prebuilt library for the target when no local build is present.
1 parent d9f7e96 commit e7474d2

6 files changed

Lines changed: 341 additions & 44 deletions

File tree

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
name: UniFFI cdylib builds
2+
3+
# Builds the livekit-uniffi dynamic library for every Dart/Flutter target and
4+
# attaches them to the livekit-uniffi release as `build-<triple>.zip` (+ a
5+
# `.sha256` sidecar). The Dart build hook (support/dart/hook/build.dart.tera)
6+
# downloads these at consumer build time.
7+
#
8+
# Reusable workflow, invoked from uniffi-packages.yml once the release tag has
9+
# been resolved. Mirrors the structure of ffi-builds.yml. Not triggered directly.
10+
11+
on:
12+
workflow_call:
13+
inputs:
14+
version:
15+
description: Release version (e.g. 0.1.1)
16+
required: true
17+
type: string
18+
tag_name:
19+
description: Source release tag (e.g. livekit-uniffi/v0.1.1)
20+
required: true
21+
type: string
22+
dry_run:
23+
description: Build artifacts but skip release upload
24+
type: boolean
25+
default: false
26+
27+
permissions:
28+
contents: write
29+
30+
jobs:
31+
build:
32+
name: Build (${{ matrix.target }})
33+
runs-on: ${{ matrix.os }}
34+
strategy:
35+
fail-fast: false
36+
matrix:
37+
include:
38+
- os: macos-latest
39+
target: aarch64-apple-darwin
40+
platform: apple
41+
- os: macos-latest
42+
target: x86_64-apple-darwin
43+
platform: apple
44+
- os: macos-latest
45+
target: aarch64-apple-ios
46+
platform: apple
47+
- os: ubuntu-latest
48+
target: x86_64-unknown-linux-gnu
49+
platform: linux
50+
- os: ubuntu-latest
51+
target: aarch64-unknown-linux-gnu
52+
platform: linux
53+
- os: windows-latest
54+
target: x86_64-pc-windows-msvc
55+
platform: windows
56+
- os: windows-latest
57+
target: aarch64-pc-windows-msvc
58+
platform: windows
59+
- os: ubuntu-latest
60+
target: aarch64-linux-android
61+
platform: android
62+
- os: ubuntu-latest
63+
target: armv7-linux-androideabi
64+
platform: android
65+
- os: ubuntu-latest
66+
target: x86_64-linux-android
67+
platform: android
68+
69+
steps:
70+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
71+
with:
72+
submodules: true
73+
74+
- name: Setup Rust toolchain
75+
uses: actions-rust-lang/setup-rust-toolchain@46268bd060767258de96ed93c1251119784f2ab6 # v1.16.1
76+
with:
77+
target: ${{ matrix.target }}
78+
cache: false
79+
# This action defaults RUSTFLAGS to "-D warnings"; clear it so
80+
# dependency warnings don't fail the build (matches ffi-builds.yml).
81+
rustflags: ""
82+
83+
- name: Install Protoc
84+
uses: arduino/setup-protoc@a8b67ba40b37d35169e222f3bb352603327985b6 # v2.1.0
85+
with:
86+
version: "25.2"
87+
repo-token: ${{ secrets.GITHUB_TOKEN }}
88+
89+
# Apple, Windows: build the cdylib directly for the target.
90+
- name: Build (Apple / Windows)
91+
if: ${{ matrix.platform == 'apple' || matrix.platform == 'windows' }}
92+
shell: bash
93+
run: cargo build --release --target ${{ matrix.target }} -p livekit-uniffi
94+
95+
# Linux: native build for x64; cross toolchain for aarch64.
96+
- name: Build (Linux)
97+
if: ${{ matrix.platform == 'linux' }}
98+
run: |
99+
if [ "${{ matrix.target }}" = "aarch64-unknown-linux-gnu" ]; then
100+
sudo apt-get update
101+
sudo apt-get install -y gcc-aarch64-linux-gnu
102+
export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc
103+
# .cargo/config.toml forces -fuse-ld=lld for this target to link
104+
# libwebrtc; livekit-uniffi doesn't use libwebrtc. A non-empty global
105+
# RUSTFLAGS overrides that per-target config, selecting the GNU bfd
106+
# linker the cross binutils provides.
107+
export RUSTFLAGS="-C link-arg=-fuse-ld=bfd"
108+
fi
109+
cargo build --release --target ${{ matrix.target }} -p livekit-uniffi
110+
111+
# Android: build with cargo-ndk.
112+
- name: Build (Android)
113+
if: ${{ matrix.platform == 'android' }}
114+
run: |
115+
cargo install cargo-ndk
116+
cargo ndk --target ${{ matrix.target }} build --release -p livekit-uniffi
117+
118+
# macOS/Linux: zip + shasum are available.
119+
- name: Package artifact (Unix)
120+
if: ${{ matrix.platform != 'windows' }}
121+
shell: bash
122+
run: |
123+
triple="${{ matrix.target }}"
124+
dir="target/${triple}/release"
125+
case "$triple" in
126+
*apple*) lib="liblivekit_uniffi.dylib" ;;
127+
*) lib="liblivekit_uniffi.so" ;;
128+
esac
129+
out="build-${triple}.zip"
130+
# Zip with the bare library name at the archive root.
131+
(cd "$dir" && zip "$GITHUB_WORKSPACE/$out" "$lib")
132+
# SHA-256 sidecar, in `shasum -a 256` format (lowercase hex first).
133+
shasum -a 256 "$out" > "$out.sha256"
134+
135+
# Windows runners lack `zip`/`shasum`; use PowerShell equivalents and
136+
# emit the same `<lowercase-hex> <file>` sidecar format the hook parses.
137+
- name: Package artifact (Windows)
138+
if: ${{ matrix.platform == 'windows' }}
139+
shell: pwsh
140+
run: |
141+
$triple = "${{ matrix.target }}"
142+
$lib = "target/$triple/release/livekit_uniffi.dll"
143+
$out = "build-$triple.zip"
144+
Compress-Archive -Path $lib -DestinationPath $out -Force
145+
$hash = (Get-FileHash -Algorithm SHA256 $out).Hash.ToLower()
146+
"$hash $out" | Out-File -Encoding ascii -NoNewline "$out.sha256"
147+
148+
- name: Upload build artifact
149+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
150+
with:
151+
name: cdylib-${{ matrix.target }}
152+
path: |
153+
build-${{ matrix.target }}.zip
154+
build-${{ matrix.target }}.zip.sha256
155+
156+
release:
157+
name: Attach cdylibs to release
158+
needs: build
159+
if: ${{ !inputs.dry_run }}
160+
runs-on: ubuntu-latest
161+
steps:
162+
- name: Download build artifacts
163+
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
164+
with:
165+
pattern: cdylib-*
166+
merge-multiple: true
167+
path: cdylibs
168+
169+
- name: Upload to release
170+
env:
171+
GH_TOKEN: ${{ github.token }}
172+
run: gh release upload "${{ inputs.tag_name }}" cdylibs/* --repo "${{ github.repository }}" --clobber

.github/workflows/uniffi-packages.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,13 @@ jobs:
7676
tag_name: ${{ needs.resolve-tag.outputs.tag_name }}
7777
dry_run: ${{ inputs.dry_run || false }}
7878
secrets: inherit
79+
80+
# Raw cdylibs for the Dart package's build-hook download (build-<triple>.zip).
81+
cdylib:
82+
needs: resolve-tag
83+
if: needs.resolve-tag.outputs.tag_name != ''
84+
uses: ./.github/workflows/uniffi-cdylib.yml
85+
with:
86+
version: ${{ needs.resolve-tag.outputs.version }}
87+
tag_name: ${{ needs.resolve-tag.outputs.tag_name }}
88+
dry_run: ${{ inputs.dry_run || false }}

livekit-uniffi/Makefile.toml

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,10 @@ SPM_NAME = "LiveKitUniFFI"
2121
NPM_NAME = "@livekit/uniffi"
2222
DART_PACKAGE_NAME = "livekit_uniffi"
2323

24-
# Base URL for downloading release builds of the cdylib.
25-
# Currently, it is assumed the archives will be named "ffi-<platform>-<arch>.zip".
26-
CDYLIB_DOWNLOAD_BASE_URL = "https://github.com/livekit/example/releases/download/example/build"
24+
# Per-release directory holding the cdylib archives published by
25+
# .github/workflows/uniffi-cdylib.yml. Downloaders append
26+
# `/v<version>/build-<triple>.zip` (and a `.sha256` sidecar).
27+
CDYLIB_DOWNLOAD_BASE_URL = "https://github.com/livekit/rust-sdks/releases/download/livekit-uniffi"
2728

2829
[config]
2930
skip_core_tasks = true
@@ -656,13 +657,18 @@ private = true
656657
extend = "tera"
657658
args = ["--env-only", "-t", "${SUPPORT_DIR}/${LANG}/pubspec.yaml.tera", "-o", "${PACKAGES_DIR}/${LANG}/pubspec.yaml"]
658659

659-
[tasks.dart-copy-hook]
660+
# Render the build hook from its template, baking in the package version and the
661+
# release download base used by the hook's download (release) mode.
662+
[tasks.dart-make-hook-dir]
660663
private = true
661664
script_runner = "@shell"
662-
script = """
663-
mkdir -p ${PACKAGES_DIR}/${LANG}/hook
664-
cp ${SUPPORT_DIR}/${LANG}/hook/build.dart ${PACKAGES_DIR}/${LANG}/hook/build.dart
665-
"""
665+
script = "mkdir -p ${PACKAGES_DIR}/${LANG}/hook"
666+
667+
[tasks.dart-copy-hook]
668+
private = true
669+
dependencies = ["dart-make-hook-dir"]
670+
extend = "tera"
671+
args = ["--env-only", "-t", "${SUPPORT_DIR}/${LANG}/hook/build.dart.tera", "-o", "${PACKAGES_DIR}/${LANG}/hook/build.dart"]
666672

667673
# Dev delivery: copy the locally built dylib into the package root, where the
668674
# build hook resolves it. A release flow would replace this with a download.

livekit-uniffi/support/dart/hook/build.dart

Lines changed: 0 additions & 36 deletions
This file was deleted.

0 commit comments

Comments
 (0)