Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-28141] iOS/macOS: Support Swift Package Manager (SPM) in modules

GitHub Issuen/a
TypeNew Feature
PriorityHigh
StatusOpen
ResolutionUnresolved
Affected Version/sn/a
Fix Version/sn/a
ComponentsiOS, Mac
Labelsn/a
ReporterHans Knöchel
AssigneeAbir Mukherjee
Created2020-09-16T14:14:38.000+0000
Updated2020-12-20T10:01:10.000+0000

Description

In the modern iOS/macOS ecosystem, the Apple-owned "Swift Package Manager" is the new way of managing external dependencies. While other solutions like Cocoapods and Carthage still exist, the future is definitely the Swift Package Manager. In general, you just ned to paste the Github link of the library into Xcode, select the version (or version range) and Xcode will find the correct version of the library. This is already possible in modules today (I wondered as well), but the problem is that the SPM settings belong into the generated app, not the module Xcode project. Technically, what it needs to support this, is *relatively* simple:

Verify the module / app extension compilation. This probably does not need *any* changes, because mainly xcodebuild is used here and that works

Copy the Package.resolved file of the module into the module zip. It looks like this:

{
  "object": {
    "pins": [
      {
        "package": "Kingfisher",
        "repositoryURL": "https://github.com/onevcat/Kingfisher",
        "state": {
          "branch": null,
          "revision": "175eeb4618b0a6ef4d69a7409b6a74ddd235a093",
          "version": "5.15.0"
        }
      }
    ]
  },
  "version": 1
}

Reference the Package.resolved during build and re-generate the pbxproj references for SPM:

/* Begin XCRemoteSwiftPackageReference section */
		3A0F5BDD251250E300E8829E /* XCRemoteSwiftPackageReference "Kingfisher" */ = {
			isa = XCRemoteSwiftPackageReference;
			repositoryURL = "https://github.com/onevcat/Kingfisher";
			requirement = {
				kind = exactVersion;
				version = 5.15.0;
			};
		};
/* End XCRemoteSwiftPackageReference section */

/* Begin XCSwiftPackageProductDependency section */
		3A0F5BDE251250E300E8829E /* KingfisherSwiftUI */ = {
			isa = XCSwiftPackageProductDependency;
			package = 3A0F5BDD251250E300E8829E /* XCRemoteSwiftPackageReference "Kingfisher" */;
			productName = KingfisherSwiftUI;
		};
		3A0F5BE0251250E300E8829E /* Kingfisher */ = {
			isa = XCSwiftPackageProductDependency;
			package = 3A0F5BDD251250E300E8829E /* XCRemoteSwiftPackageReference "Kingfisher" */;
			productName = Kingfisher;
		};
/* End XCSwiftPackageProductDependency section */
All required data of that can be received from the Package.resolved file of each module :-)

Finally: Add the framework references to the pbxproj like before, e.g.

		3A0F5BDF251250E300E8829E /* KingfisherSwiftUI in Frameworks */ = {isa = PBXBuildFile; productRef = 3A0F5BDE251250E300E8829E /* KingfisherSwiftUI */; };
		3A0F5BE1251250E300E8829E /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 3A0F5BE0251250E300E8829E /* Kingfisher */; };
I can assist with sample projects and further information if requested! P.S.: Supporting this, modules will also shrink in size by > 95% and make the Appc Github CI happy :)

Comments

  1. Hans Knöchel 2020-12-20

    An early PoC of modules using Swift Package Manager (SPM) dependencies for the Facebook SDK: https://github.com/appcelerator-modules/ti.facebook/pull/192 The open issue is described in the issue: {quote} This was the easy part. The tricky part will be how to pull these dependencies into the generated project. The solution could be to package the whole module project and do not attempt to generate a module library at all. That's basically was SPM does as well. Xcode will handle the framework caching in the DerivedData directory and Titanium "just" embeds each module project into the main project. An alternative could be that Titanium maintains an own config file for it's iOS dependencies, but that would (again) introduce an additional overhead to be handled manually. {quote} Open for discussion!

JSON Source