4

Using Xcode 12.4 and Swift 5.3 I have defined a package using the Package.swift manifest file. After including it in an app I want to update the package. To do that I have changed the link to the new release and updated the checksum; the relevant part of the file looks like this:

let package = Package(
    name: "MyPackage",
    // omitted platforms and products
    targets: [ .binaryTarget( name: "MyPackage",
                              url: "https://artifactory/mypackage-v1.1.zip",
                              checksum: "..." ) ] )

However, I get the error message artifact of binary target 'MyPackage' has changed checksum; this is a potential security risk so the new artifact won't be downloaded. This error can be ignored by deleting the entire DerivedData on folder, but that's obviously not updating the version number. Another solution is suggested in this answer, but again it doesn't affect versioning. The official documentation writes extensively about dependent package versions, but I cannot find how to specify the version of the CURRENT package.

How can I legitimately specify and update the version number so the new artifact gets identified as a distinct new version and downloaded properly?

user8472
  • 3,268
  • 3
  • 35
  • 62
  • It's my understanding, that the "version" is the URL, and you need a valid tuple: (content_of_the_URL, checksum). Did you create the checksum as specified here: [Declare a Binary Target in the Package Manifest](https://developer.apple.com/documentation/swift_packages/distributing_binary_frameworks_as_swift_packages)? – CouchDeveloper Feb 22 '21 at 07:51
  • 1
    Isn't in SPM versions managed with the tag on the git repo? https://developer.apple.com/documentation/xcode/publishing_a_swift_package_with_xcode – Larme Feb 22 '21 at 07:51
  • @CouchDeveloper, that would make sense. However, changing the URL and the checksum results in the above error message. – user8472 Feb 22 '21 at 07:54
  • @Lame, that would be a rather weird way to specify a version number. Plus, it obviously won't work if the version number was INSIDE the artifact since Xcode refused to download that artifact in the first place. – user8472 Feb 22 '21 at 07:54
  • 2
    Package version is specified as a tag on a commit that you push. – matt Feb 22 '21 at 07:56
  • @matt, as pointed out before this wouldn't work since such a the version number would be INSIDE the artifact and the artifact is not downloaded in the first place. – user8472 Feb 22 '21 at 08:15
  • @matt Note, it's a _binary_ package. For regular git repos, we use a git tag like "1.1.0" as the version. – CouchDeveloper Feb 22 '21 at 11:32
  • @user8472 you probably never added a tag in your git repository that has the `Package.swift` file. By doing that, when you try to install your package you are selecting the `master` branch in the `Choose Package Options` section. If you change the `url` and `checksum` in your `Package.swift` and commit then there is no way for Xcode to identify that you want to install a new version, since the repo's branch is the only thing that knows. So, Xcode thinks that this is the same version but with a different `checksum` and that's why you are getting this error. – gcharita Feb 22 '21 at 13:02
  • @gcharita, your assumption is correct. The app repository that uses the Swift package and contains the `Package.swift` manifest does not get tagged with the version of the Swift package, but with the version of the app. Are you suggesting to tag the APP REPOSITORY with version tags for the PACKAGE in order to manage the PACKAGE versions? – user8472 Feb 22 '21 at 15:33
  • @user8472 no, I am talking about the library's repository. (the `Package.swift` file that defines the `binaryTarget`) You need to add tags to the library's repository, in order for the Xcode to know which commit has the correct `Package.swift` file for each version. – gcharita Feb 22 '21 at 15:41
  • @gcharita, the `Package.swift` manifest is checked in into the app's repository. It references the binary target which supplies an xcframework file. The app's repository does not know about that package's repository. I want to supply only the xcframework, not its source code. Maybe my setup is incorrect for that use case, could you post a response and elaborate, please? – user8472 Feb 22 '21 at 15:50

1 Answers1

8

When you want to distribute (privately or publicly) a closed source package using an xcframework file you typically need to create a git repository that only contains the Package.swift file in which you declare the binaryTarget. (or the binaryTargets) Whichever have access to this repository should also have access to the url that you declare in the binaryTarget in order to install your package.

As @Larme and @matt correctly mentioned in the comments, to specify which commit correspond to each version, you have to use tags in the git repository exactly like you do in a cocoapod repository, only you will do this in a repository that contains only the Package.swift file. See "Tag Your Latest Commit" section in the Publishing a Swift Package with Xcode documentation for more details.

You can use as an example the PSPDFKit, which is a known and well maintained closed source package that can be installed using this github repository.

gcharita
  • 7,729
  • 3
  • 20
  • 37
  • It has to be a separate Git repository? Can't I use a KMM (kotlin multiplatform) repo with a subfolder called `swiftpackage`? – IgorGanapolsky Jun 10 '21 at 15:48
  • 1
    @IgorGanapolsky you can use your already existing repository for this purpose, but you have to make sure that the `Package.swift` manifest file is located in the root of the repo. You can test your configuration locally (without pushing your commits) using `file://` as package repository URL in a test Xcode project, to see if everything works as expected. – gcharita Jun 10 '21 at 16:42