Answering my own question, here's a workaround for the fact that #if targetEnvironment(simulator)
doesn't work in a Package.swift file. (Note, this workaround only works when building for iOS device or iOS simulator. A more sophisticated method would need to be used if building for other platforms, but the same principles should still apply.
// swift-tools-version:5.3
import PackageDescription
import Foundation
let base = "${PROJECT_DIR}/../../Carthage/Build/SwiftProtobuf.xcframework"
/// If building for simulator, this will resolve to
/// "/ios-arm64_i386_x86_64-iphonesimulator", causing simDir to be a
/// valid path. Otherwise it will be an invalid path, which only results
/// in a compiler warning. (If both `simDir` and `realDir` are valid paths,
/// we get a build error, so one of them needs to be invalid.)
let simDir = base + "/ios-arm64_i386_x86_64" + "${LLVM_TARGET_TRIPLE_SUFFIX}"
/// If building for device, this will be unaffected, causing realDir
/// to be a valid path. Otherwise it will be an invalid path, which only
/// results in a compiler warning. (If both `simDir` and `realDir` are valid paths,
/// we get a build error, so one of them needs to be invalid.)
let realDir = base + "/ios-arm64_armv7" + "${LLVM_TARGET_TRIPLE_SUFFIX}"
let package = Package(
name: "REDACTED",
platforms: [
.iOS(.v13),
],
products: [
.library(
name: "REDACTED",
type: .dynamic,
targets: ["REDACTED"]
),
],
dependencies: [],
targets: [
.target(
name: "REDACTED"
,swiftSettings: [
.unsafeFlags([
"-Fsystem", simDir,
"-Fsystem", realDir,
]),
]
,linkerSettings: [
.linkedFramework("SwiftProtobuf"),
.unsafeFlags([
"-Xlinker", "-rpath", "-Xlinker", simDir,
"-Xlinker", "-F", "-Xlinker", simDir,
"-Xlinker", "-rpath", "-Xlinker", realDir,
"-Xlinker", "-F", "-Xlinker", realDir,
])
]
),
]
)
This package can be used by other local packages without complaints from the compiler.
NOTE: link this to an Xcode project, you must wrap it in another local package that has no unsafe flags, where the only source file has @_exported import PACKAGENAME
at the top. Then the app will link to this wrapper and get the wrapped version.
This is seems to be a valid workaround for linking Carthage dependency XCFrameworks to local Swift Packages. Haven't tried in production yet but seems to actually work so far. YMMV.