Creating a Swift Package from an existing iOS Framework (Library)

I wasn’t sure of what title to give this article. I had another in mind, “Publishing an iOS library as a framework and as a Swift Package” but that could have made the article longer than I wanted. So, let’s go with what I have up there, hope you get the idea.

Do you have an existing iOS framework you’ve probably made available using Cocoapods or Carthage, but which you want to make available as Swift Package? Or do you want to create a new iOS library and make sure it’s available as a Swift Package as well as using other integration methods? You’ve found the right article.

Creating a library starting it as a Swift Package means no framework is generated automatically, instead your library is distributed as pure source code. However, you can generate an XCFramework using a tool like this.

If however, you have an existing framework or you’ve just created one and would want the users of your library to be able to integrate it into their project using SPM, it’s easy and with just a few steps, you are good to go.

Package.swift

The major component of a Swift Package that makes it a Swift Package is the presence of a file named Package.swift. This file is more of a manifest file that contains all there is to know about the Swift Package.

Below is a sample Package.swift file, specifying information such as the package name, product executable, dependencies and target (more info about each in the comment).

// swift-tools-version:5.3
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
    name: "RippleView",
    platforms: [
        .macOS(.v11), .iOS(.v13)
    ],
    products: [
        // Products define the executables and libraries a package produces, and make them visible to other packages.
        .library(
            name: "RippleView",
            targets: ["RippleView"]),
    ],
    dependencies: [
        // Dependencies declare other packages that this package depends on.
        // .package(url: /* package url */, from: "1.0.0"),
    ],
    targets: [
        // Targets are the basic building blocks of a package. A target can define a module or a test suite.
        // Targets can depend on other targets in this package, and on products in packages this package depends on.
        .target(
            name: "RippleView",
            dependencies: []),
        .testTarget(
            name: "RippleViewTests",
            dependencies: ["RippleView"]),
    ]
)

To get your existing framework to support integration as Swift Package, all you need to do is create a Package.swift file in your project directory and fill in the basic required information as shown in the sample above but with correct info specific to your library. However, the most important part to take note of when trying to use an existing framework is the target path. This points to the folder containing the source code for the library. So, all you need to do is to point the path to the folder containing the source code for your framework.

Below is a sample library that has been created as a framework, with this folder structure.

Sample Library Project Structure

All that is required is to point the target path to the library source code folder, Swapi/Swapi.

Target path specified

And that’s it. You push the update to Github and you are live! Anyone can now integrate your library as a Swift Package using SPM.