Swift Package Manager, same as it ever was
After working on a framework built with Objective-C, I bundled the
framework variants into an XCFramework and set up a Package.swift
manifest for distributing SDK releases. While doing so, I ran into the
following conundrum:
I want to make releases like this: bump the version number, make a
release commit; build the binaries and embed version identifier in in
the binaries as Framework vM.m.p:branch@hash:config
(where M
is
major, m
is minor, and p
is the patch components of the version
string); create the release on GitHub with the tag vM.m.p
and attach
the binaries to the GitHub release. Binaries are available in both
signed and unsigned variants—so no binary voodoo is possible, even
if that would fix my problem.
Trouble is the Swift Package Manager expects the package manifest at
the root of repository named Package.swift
and to deliver binaries,
the package manifest must contain URLs to the ZIP'd binaries and
checksum of those ZIP files. That means I'd have to make a second
separate commit to update the package manifest—now the binaries
point to the commit before the package manifest was updated and the
manifest tagged at M.m.p
actually points to the previous release.
The framework is a commercial open source product, but I don't want to support peoples "modifications" in the wild. They're free to do so, but if they send a support ticket and the log shows a version identifier that didn't originate in my source tree, good luck. In reality I wouldn't be so harsh, just send me your changes as a PR—then I can help.
So to fix this I have two bad options, don't embed the branch and hash
info for all builds, meaning M.m.p
could be any built version from
M.m.p
ahead by some arbitrary number of commits. Or build separate
Swift PM only binaries with version identifiers of the from Framework
vM.m.p:branch@hash+swiftpm:config
, so I know hash
is probably
equivalent to releasetag^
.
I picked the latter option. That means Unity, CocoaPods, Carthage, and manual integrations will always be uniquely identifiable, but I have to do extra work for Swift PM and the version identifier is just a crumb trail.
Other potential options could be putting Package.swift
in a separate
repo, but that sucks too. Or putting Package.swift
in an orphaned
branch, but that would still mean the release tags are wrong for Swift
PM. Nevertheless, both these options would require telling publishers
that they have to do extra stuff to make Swift PM work and that's
error prone at best.
Anyway, just ranting. Unless I'm overlooking and obvious way to break a cyclic graph. Package managers are great, until they're not.
Last modified: 2025-04-05 10:59:11 -0500 CDT