diff --git a/kmp/shared-core/spm/.gitignore b/kmp/shared-core/spm/.gitignore new file mode 100644 index 000000000..b53258420 --- /dev/null +++ b/kmp/shared-core/spm/.gitignore @@ -0,0 +1,3 @@ +# Left behind by `swift package` / `xcodebuild` runs against this package. +.build/ +.swiftpm/ diff --git a/kmp/shared-core/spm/Package.swift b/kmp/shared-core/spm/Package.swift index bb4746055..7ab786038 100644 --- a/kmp/shared-core/spm/Package.swift +++ b/kmp/shared-core/spm/Package.swift @@ -1,5 +1,6 @@ // swift-tools-version:5.9 import PackageDescription +import Foundation // The publish job rewrites this block — everything else in this file is ours. Note the // tags are load-bearing: KMMBridge looks for them verbatim and fails the publish if @@ -10,6 +11,46 @@ let remoteKotlinChecksum = "b86241d770fa186e44eec4c9ff0ff092d54cf66329828485d243 let packageName = "SharedCore" // END KMMBRIDGE BLOCK +// FLIPCASH_SHARED_CORE_LOCAL points at a code-android-app checkout and swaps the published +// XCFramework for one assembled from that checkout's Kotlin, so a Kotlin change can be tried +// from an iOS build without cutting a release and moving a tag: +// +// ./gradlew :kmp:shared-core:assembleSharedCoreReleaseXCFramework +// +// This manifest is what gets published, so the override also works from the tagged copy the +// iOS app resolves — nothing on the iOS side has to change. That copy sits in DerivedData, and +// SwiftPM only accepts a binary target path relative to the package root, so the absolute path +// the variable gives us is rewritten as a relative one from wherever the manifest was checked +// out to. +// +// The publish workflow never sets the variable, so CI always resolves the binary target +// through the URL and checksum above. +func relativePath(from base: String, to target: String) -> String { + let from = (base as NSString).resolvingSymlinksInPath.split(separator: "/").map(String.init) + let to = (target as NSString).resolvingSymlinksInPath.split(separator: "/").map(String.init) + var shared = 0 + while shared < from.count, shared < to.count, from[shared] == to[shared] { shared += 1 } + return (Array(repeating: "..", count: from.count - shared) + to[shared...]).joined(separator: "/") +} + +let sharedCoreLocalRoot = ProcessInfo.processInfo.environment["FLIPCASH_SHARED_CORE_LOCAL"] + .map { ($0 as NSString).expandingTildeInPath } + .flatMap { $0.isEmpty ? nil : $0 } + +let binaryTarget: Target = sharedCoreLocalRoot.map { + .binaryTarget( + name: packageName, + path: relativePath( + from: Context.packageDirectory, + to: "\($0)/kmp/shared-core/build/XCFrameworks/release/\(packageName).xcframework" + ) + ) +} ?? .binaryTarget( + name: packageName, + url: remoteKotlinUrl, + checksum: remoteKotlinChecksum +) + let package = Package( name: packageName, platforms: [ @@ -25,11 +66,7 @@ let package = Package( ), ], targets: [ - .binaryTarget( - name: packageName, - url: remoteKotlinUrl, - checksum: remoteKotlinChecksum - ), + binaryTarget, .target( name: "SharedCoreKit", dependencies: [.target(name: packageName)]