I have been working on exporting a Kotlin multiplatform module from an Android project into a Github release as an XCFramework, so that I can utilize the logic in an iOS project in XCode. I've been using this tutorial from kotlinlang and it has been working great until today. I had everything working and could add the XCFramework as a dependency to my project in XCode. However, something has changed today while I've been working on this, so now I can't validate the XCFramework zip file locally or download it in the XCode project. I have a few different XCFrameworks in different repos, both in my personal Github and in my company's Github, and some of both private and public. For all, I try to run the command from the tutorial to validate the manifests:
swift package reset && swift package show-dependencies --format json
Each one gives the same response:
Downloading binary artifact https://github.com/{{accountNameHere}}/kmm/releases/download/v1.4.0/Shared.xcframework.zip
error: failed downloading 'https://github.com/{{accountNameHere}}/kmm/releases/download/v1.4.0/Shared.xcframework.zip' which is required by binary target 'Shared':
badResponseStatusCode(404)
error: fatalError
When I try to add the package dependency in XCode, it finds the package in the repository but can't seem to read the contents. It warns me "Unable to load the Read Me" and then, when I click Add Package, fails with the error "invalid archive returned from 'https://github.com/..........'.
I've cleared the Swift PM caches and DerivedData folder to no avail. I even created a completely new project with a shared module, created the XCFramework artifact, zipped it, and published it in a release in a new Github repo. Even with everything brand new and simple, I got the same error messages. Since the error message doesn't say anything about what is invalid about the archive, I don't know what might be wrong. I've downloaded the zip file directly from the release, and it is in the correct format.
I'm at a loss here on what could be wrong or what else I can try. I've posted this question on JetBrains YouTrack as well. Any advice would be hugely appreciated. Thank you.
That doc is not complete. It explains how to create an XCFramework zip, but from there you're on your own. Accessing those zips from Xcode is not complicated exactly, but the errors you're seeing can be confusing.
You've stated that your library was "working" previously, but I'm not sure how that's possible.
Specifically, regardless of if you have a public or private repo, to download binaries from GitHub, you need to set up authentication to access them. Also, I don't believe Xcode will properly follow redirects, at least with auth, so you'll need the resolved URL for the release artifact. Not the "simple" URL.
https://github.com/{{accountNameHere}}/kmm/releases/download/v1.4.0/Shared.xcframework.zip
That is the URL that you get when you look at the release and click "copy URL", but unless something with GitHub and/or Xcode has changed in the last few months, you'll want to call the GitHub API to get the actual direct URL.
We built a library for publishing XCFrameworks: https://kmmbridge.touchlab.co/. A new version should be out later this week or early next week which is simpler for SPM.
In any case, public or private, you'll need to set up auth to access binaries from GitHub. This is the process (these docs are part of the new version):
https://touchlab.co/kmmbridge/spmquickstart#spm-and-xcode
For completeness, if anybody finds this answer, you also can't directly use Maven or Amazon S3. KMMBridge "uses" Maven, but not how you'd think, and Amazon S3 can only be used if you make the URL public, which most companies would probably not be excited about. (Amazon S3 has no basic auth access option, which is necessary for Xcode access).
If you want a sense for what's involved with something like Amazon S3, see this post: https://engineering.premise.com/publishing-kotlin-multiplatform-swift-packages-to-google-cloud-storage-be5c6987e5d. It's with Google Cloud Run, but it's the same problem (no basic auth).
I also wouldn't personally publish SPM to a separate repo, unless the repo in which your KMP code resides would have conflicting versions. Publishing across repos is more complex (deploy keys, etc), and kind of confusing to have the code in one place and the library in another (but, again, that's personal preference).
Looking at the URL, I see the version is v1.4.0
. SPM is very picky about version strings. They want to be strict semver. It'll "work", but you'll have to flush caches (or something like that, I forget the exact details). So, I'd highly recommend 1.4.0
, no v
prefix.