I'd like to pitch adding a way to link a local Swift Package to a local XCFramework anywhere on the same hard drive.
Proposed Solution
It would work like this:
let package = Package(
name: "SwiftUISnapshotTestCase",
platforms: [
.iOS(.v13),
],
products: [
.library(
name: "SwiftUISnapshotTestCase",
targets: ["SwiftUISnapshotTestCase"]
),
],
dependencies: [ .xcframework(relativePath: "../../Carthage/Build/FBSnapshotTestCase.xcframework")]
targets: [
.target(
name: "SwiftUISnapshotTestCase",
dependencies: ["FBSnapshotTestCase"]
)
]
)
Rationale
Currently we are reduced to this kind of garbage when we want to link to an XCFramework in our Carthage folder:
// swift-tools-version:5.3
import PackageDescription
let base = "${PROJECT_DIR}/../../../Carthage/Build/FBSnapshotTestCase.xcframework"
let base2 = "${PROJECT_DIR}/../../Carthage/Build/FBSnapshotTestCase.xcframework"
let simDir = base + "/ios-arm64_x86_64" + "${LLVM_TARGET_TRIPLE_SUFFIX}"
let realDir = base + "/ios-arm64" + "${LLVM_TARGET_TRIPLE_SUFFIX}"
let simDir2 = base2 + "/ios-arm64_x86_64" + "${LLVM_TARGET_TRIPLE_SUFFIX}"
let realDir2 = base2 + "/ios-arm64" + "${LLVM_TARGET_TRIPLE_SUFFIX}"
let package = Package(
name: "SwiftUISnapshotTestCase",
platforms: [
.iOS(.v13),
],
products: [
.library(
name: "SwiftUISnapshotTestCase",
targets: ["SwiftUISnapshotTestCase"]
),
],
targets: [
.target(
name: "SwiftUISnapshotTestCase",
swiftSettings: [
.unsafeFlags([
"-Fsystem", simDir,
"-Fsystem", realDir,
]),
],
linkerSettings: [
.linkedFramework("FBSnapshotTestCase"),
.unsafeFlags([
"-Xlinker", "-F", "-Xlinker", simDir,
"-Xlinker", "-F", "-Xlinker", realDir,
"-Xlinker", "-F", "-Xlinker", simDir2,
"-Xlinker", "-F", "-Xlinker", realDir2,
])
]
),
]
)
We have to do this ugly hack because other packages that may link to this guy, are in different levels of nesting within the work space—some are 3 levels, some are 2 levels. It's incredibly annoying to have to put an ugly hack like this, which always generates lots of superfluous warnings, just to do a simple thing like link Swift Package to an XCFramework from the Carthage folder.
Alternatives Considered
We have considered using Swift Package versions of our Carthage dependencies but the Xcode-SPM integration makes it take forever to open the workspace if your packages aren't downloaded already, and it requires all the source packages to be visible within Xcode which makes our already slow workspace run even worse and be more cluttered. Our CI system is integrated with Carthage using a custom cacheing solution that it would be non-trivial to rewrite to handle cacheing of pre-built SPM dependencies and there's no way for SPM to automatically build all the dependencies as XCFrameworks that don't have to be rebuilt every time a new version of the compiler is issued forth. So we are sticking with the tried and true Carthage for now, and are only using SPM as a way to avoid using Xcode projects for declaring local modules.
As such we don't need SPM's "safety" restrictions which are designed to prevent malicious third-party packages from wreaking havoc on your computer. All our packages are our own source-code. We just want more flexibility to use these packages the same ways that Xcode projects can be used, like being able to link them to our Carthage dependencies.
I also tried pitching the idea of creating a second kind of Swift Package called a "Swift Project" that would be for your local code, but this idea was shot down and I was told to just make the suggestions to improve Swift Packages. After awhile of considering how to boil it down to one simple request, here I am.
Thanks for your consideration.