This repository publishes a Swift Package Manager binary distribution for
libwebp. It builds mergeable Apple
XCFramework assets from upstream release tags and publishes them as GitHub
Releases so Swift clients can depend on versioned binaries instead of
rebuilding libwebp from source.
This repository is a packaging wrapper, not an upstream source mirror. It keeps only packaging automation, generated package metadata, tests, and license notices while CI dynamically fetches upstream source snapshots for builds.
Each release publishes five binary targets:
WebPWebPDecoderWebPDemuxWebPMuxSharpYuv
The build matrix covers mergeable slices for:
- iOS
- iOS Simulator
- macOS
- Mac Catalyst
- tvOS
- tvOS Simulator
- watchOS
- watchOS Simulator
- visionOS
- visionOS Simulator
- Upstream source of truth:
https://github.com/webmproject/libwebp - Automatic publishing: the
publish-latest-upstream-alphaworkflow checks upstream stable tags (vX.Y.Z) on a schedule, selects the newest upstream stable source snapshot, and publishes or repairs the matching package prerelease. Alpha publishes remain prerelease-only and do not update the default branchPackage.swift. - Manual backfill: the
publish-upstream-release-manuallyworkflow publishes a specific stable upstream tag without requiring the repository to catch up through every historical version, and the operator must explicitly choose whether the package release should stay on thealphachannel or publish the stable package tag. - Package tags: this repository owns the SwiftPM semver tags that clients
consume. Stable public releases use
X.Y.Z. Alpha package tags such asX.Y.Z-alpha.Nremain available for prerelease validation and can increment on the same upstream stable release whenever the packaging pipeline needs another prerelease cut. - The user-facing publish workflows delegate to a shared
publish-package-release-corereusable workflow so scheduled and manual release paths stay on the same resolve, build, manifest, and publication logic while isolating the expensive XCFramework build from the final publish step. - Source acquisition is defined by
config/source-acquisition.json. CI builds from exported upstream tag snapshots instead of assuming the checked-out repository state is the release source of truth. - Apple deployment targets and build-matrix ownership are centralized in
config/platforms.json.Package.swift, the Apple archive matrix, and plan introspection all derive from that single data model instead of hand-maintained per-call-site literals. - CI compiler caching follows a narrow policy: persist only
.ccachewithactions/cache, scope it by cache schema, runner OS, Xcode version, upstream source commit, and repo-local build script inputs, and avoid cachingDerivedDataor other opaque Xcode build directories by default. Cache saves are gated on a successful restore step, a successful compile-heavy build step, and a non-empty.ccachepayload so failed pre-build runs cannot publish poisoned empty cache snapshots. If a poisoned cache line is discovered, the workflow rotates away from it with a cache-schema bump. - Stable package tags such as
X.Y.Zare reserved for the manual workflow. If a stable tag already exists with different generated package metadata, the workflow fails instead of overwriting published public artifacts. - During this rollout, a rerun may keep repairing the latest matching
X.Y.Z-alpha.Nrelease or mint the nextalpha.Nif the generated package payload changed. - If the latest alpha tag for an upstream release already matches the generated
Package.swiftbut the GitHub Release is incomplete, the workflow repairs the missing assets instead of silently minting another prerelease number. - Alpha GitHub Releases are explicitly published as prereleases and are
normalized to
latest=falseso automated prerelease tags do not become the repository's public latest release by accident. - Upstream tags are fetched into a dedicated
refs/upstream-tags/*namespace in CI to avoid tag-name collisions with published package versions. - The published binaries are mergeable dynamic libraries packaged as XCFrameworks. There is no static-library fallback release track.
For public consumption, depend on a stable package release:
dependencies: [
.package(url: "https://github.com/<owner>/<repository>.git", from: "1.6.0")
]Replace <owner>/<repository> with the GitHub repository that publishes your
release assets. If you publish the package as libwebp, use that package
identity in downstream dependencies.
If you need to validate a prerelease packaging cut before a stable publish, pin an explicit prerelease version instead:
dependencies: [
.package(url: "https://github.com/<owner>/<repository>.git", exact: "1.6.0-alpha.12")
]Then depend on one or more binary products:
targets: [
.target(
name: "YourTarget",
dependencies: [
.product(name: "WebP", package: "libwebp"),
.product(name: "WebPDemux", package: "libwebp"),
]
)
]The published products include the linked binary closure needed by each dynamic
library. WebP bundles SharpYuv, and both WebPDemux and WebPMux bundle
WebP plus SharpYuv, so consumers should depend on the highest-level product
they need instead of manually repeating those lower-level package products.
Package.swift is generated by release automation for each published package
tag and points to the matching release assets plus their checksums.
To let Xcode treat these binaries as mergeable inputs, enable merged binaries on the consuming app or framework target for Release builds:
MERGED_BINARY_TYPE = automatic
Debug builds can keep the default dynamic-link behavior.
The repository ships two release helpers:
scripts/spm_release.py: selects stable upstream tags, derives package prerelease tags, rendersPackage.swift, computes checksums, prints the Apple build matrix, builds mergeable XCFrameworks, validates mergeable metadata, and runs local macOS consumer smoke tests for both the direct XCFramework path and a real SwiftPM binary-target integration in Debug and Release. It keeps the CLI surface stable while delegating stable rules toscripts/spm_release_support/modules for platform contract, release planning, and package-validation logic. It also owns the repo-local source acquisition contract used by CI to fetch and export upstream source snapshots.scripts/build_apple_xcframeworks.sh: thin wrapper around the Python release tool for local use and CI..github/workflows/validate-apple-release-pipeline.yml: validates not only the XCFramework build output but also the renderedPackage.swiftcontract for those freshly built artifacts. Manual dispatch can optionally pin a specific upstream stable tag for reproducible validation.
Example local build:
python3 scripts/spm_release.py fetch-upstream-tags --remote upstream
python3 scripts/spm_release.py export-upstream-source \
--tag v1.6.0 \
--output-dir /tmp/libwebp-source
./scripts/build_apple_xcframeworks.sh \
--source-dir /tmp/libwebp-source \
--output-dir /tmp/libwebp-artifacts \
--tag 1.6.0-alpha.1 \
--keep-xcframeworksBuild prerequisites:
- Xcode with iOS, macOS, tvOS, watchOS, and visionOS SDKs installed
- Python 3.10+
cmakexcrun vtool- Swift toolchain with
swift package compute-checksum - Requested Apple platform destinations must be available in Xcode; the build now fails fast instead of silently emitting a mislabeled fallback slice.
- This repository is not a pure mirror of upstream
libwebp. - The repository intentionally excludes the upstream
libwebpsource tree. Local debugging should use an exported upstream snapshot or a separate clone of the upstream project. - Stable package tags are the public SwiftPM release surface. Alpha tags remain available only for prerelease validation and repair publishes.
watchOSmergeable slices are published forarm64andarm64_32;armv7kis intentionally excluded because the current Apple linker does not support mergeable output for that architecture.- If a release job fails after pushing a tag but before uploading all assets, rerun the manual backfill workflow for the same tag. The workflow now repairs the existing GitHub Release instead of rejecting the already-published tag.
- Wrapper package contract and workflow guide: docs/how-to-build/swiftpm-binary-package.md
This repository and its distributed binary frameworks are licensed under the BSD 3-Clause License (see COPYING) and the Additional IP Rights Grant (see PATENTS), identical to upstream webmproject/libwebp.
New releases record immutable upstream and wrapper input identity in
config/release-inputs.json. Scheduled and manual alpha use the same reuse/evaluate
policy and repository publication lock. See the
repeat-publication SOP
for source pinning, legacy tags, strict repair checks, and verification boundaries.
Actions uses the same stage vocabulary across the wrapper repositories:
Verify → Resolve → Build (product) → Validate Consumers → Publish → Summary.
Validation runs omit publication. CPU/Vulkan products are separate branches;
platform slices remain grouped within each build job. Consumer jobs verify archive
transfer digests and test the final extracted XCFrameworks in Debug and Release.
A failed consumer blocks publication. Completed matching releases use the Reuse
path; metadata-only drift uses Repair Metadata without rebuilding.
Consume an accepted package version tag, rather than the default branch. Alpha releases do not promote default-branch package metadata; a successful CI run alone does not establish that the default-branch binary URLs are downloadable. The Summary job records stage results and links to the run artifacts. Each build artifact inventory records upstream commit, toolchain and archive SHA-256 values.
This repository's scripts and tests own its executable package contract. The shared policy references are input identity and Alpha name allocation, publication and repair decisions, and the Actions stage contract. Use accepted version tags; Alpha publication does not promote the default-branch manifest.