Simple Nested Libraries, With the Top One Being Dynamic
In this example, the PackageConsumer
utility simply consumes Package_C
, Version 1.0.0, which is a dynamic library, that, in turn, consumes Package_A
Version 1.0.0 (a static library).
Here is the GitHub link to the PackageConsumer
project Version 3.0.0. You can check out that version, and reproduce the results here.
The reason for the red line and the “NO” symbol, is because there are some issues that can arise, when running in Xcode, due to the Hardened Runtime setting (more on that, below).
Here is the source code for the Package_C.swift
file, Version 1.0.0:
import Foundation import Package_A public struct Package_C: 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_C, Version: 1.0.0\n" + Package_A(indent: inIndent + 1).text } }
Here is the source for the Package_C
Package.swift
file:
import PackageDescription let package = Package( name: "Package_C", platforms: [ .iOS(.v11), .tvOS(.v11), .macOS(.v10_14), .watchOS(.v5) ], products: [ .library( name: "Package-C", type: .dynamic, targets: ["Package_C"]) ], dependencies: [ .package(name: "Package_A", url: "git@github.com:LittleGreenViper/SPMArticle-Package_A.git", from: "1.0.0") ], targets: [ .target( name: "Package_C", dependencies: [ .product(name: "Package-A", package: "Package_A") ] ), .testTarget( name: "Package_CTests", dependencies: [ "Package_C" ] ) ] )
Note the “type: .dynamic
“, in the products list. That tells the build system to create the library as a dylib/framework.
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" } }
Here is the source for the PackageConsumer
Version 3.0.0 file:
import Foundation import Package_C struct PackageConsumer { let text: String init(text intext: String = "PackageConsumer, Version 3.0.0") { text = intext + "\n" + Package_C(indent: 1).text } }
Running that, gives us something like this in the console:
PackageConsumer, Version 3.0.0 Package_C, Version: 1.0.0 Package_A, Version: 1.0.0
An Important Note About Running This In Xcode
Because this imports a dynamic library, the library needs to be embedded, which means that it also needs to be signed.
If we have Hardened Runtime on, then the execution will fail:
If we have it off, the execution will work:
This does not happen when we use swift build
. I suspect that’s because swift build
does not enable Hardened Runtime by default.