Swift Package Manager Logo

Implementing Swift Package Manager –Example 2

This entry is part 8 of 14 in the series Swift Package Manager

Simple, Nested Static Libraries

In this example, the PackageConsumer utility simply consumes Package_BPrime, Version 1.0.0, which is a static library, that, in turn, consumes Package_A Version 1.0.0 (also a static library).

Here is the GitHub link to the PackageConsumer project Version 2.0.0. You can check out that version, and reproduce the results here.

Fig. 1: The Hierarchy

Here is the source code for Package_BPrime, version 1.0.0:

import Foundation
import Package_A

public struct Package_BPrime: PackageProtocol {
    public let indent: Int
    public let text: String
    public init(indent inIndent: Int = 0) {
        indent = inIndent
        let prefix = String(repeating: "\t", count: inIndent)
        text =  "\(prefix)Package_BPrime, Version: 1.0.0\n" + Package_A(indent: inIndent + 1).text
    }
}

Here is the source for the Package_BPrime, Version 1.0.0 Package.swift file:

import PackageDescription

let package = Package(
    name: "Package_BPrime",
    platforms: [
        .iOS(.v11),
        .tvOS(.v11),
        .macOS(.v10_14),
        .watchOS(.v5)
    ],
    products: [
        .library(
            name: "Package-BPrime",
            targets: ["Package_BPrime"]),
    ],
    dependencies: [
        .package(name: "Package_A", url: "git@github.com:LittleGreenViper/SPMArticle-Package_A.git", from: "1.0.0")
    ],
    targets: [
        .target(
            name: "Package_BPrime",
            dependencies: [
                .product(name: "Package-A", package: "Package_A")
            ]
        ),
        .testTarget(
            name: "Package_BPrimeTests",
            dependencies: ["Package_BPrime"]
        ),
    ]
)

Here is the source code for Package_A, version 1.0.0:

import Foundation

public protocol PackageProtocol {
    var text: String { get }
    var indent: Int { get }
}

public struct Package_A: PackageProtocol {
    public let indent: Int
    public let text: String
    public init(indent inIndent: Int = 0) {
        indent = inIndent
        let prefix = String(repeating: "\t", count: inIndent)
        text =  "\(prefix)Package_A, Version: 1.0.0"
    }
}

And here is its Package.swift file:

import PackageDescription

let package = Package(
    name: "Package_A",
    platforms: [
        .iOS(.v11),
        .tvOS(.v11),
        .macOS(.v10_14),
        .watchOS(.v5)
    ],
    products: [
        .library(
            name: "Package-A",
            targets: ["Package_A"]),
    ],
    targets: [
        .target(
            name: "Package_A",
            dependencies: []),
        .testTarget(
            name: "Package_ATests",
            dependencies: ["Package_A"]),
    ]
)

Here is the source for the PackageConsumer Version 2.0.0 file:

import Foundation
import Package_BPrime

struct PackageConsumer {
    let text: String
    init(text intext: String = "PackageConsumer, Version 2.0.0") {
        text = intext + "\n" + Package_BPrime(indent: 1).text
    }
}

Running that, gives us something like this in the console:

PackageConsumer, Version 2.0.0
	Package_BPrime, Version: 1.0.0
		Package_A, Version: 1.0.0

Why “Package_BPrime“?

This was because I found out that there seems to be some built-in module with an exposed module namespace of “Package_B,” and declaring the package with that import name caused a very strange collision. Debugging this took me the better part of a day.