Batch-iOS-SDK
Batch-iOS-SDK copied to clipboard
Batch 2.x is not linked at runtime using CocoaPods 1.15.2 (last version)
Summary
I try to upgrade Batch SDK from 1.21.2 to 2.0.1 with CocoaPods last version (1.15.2).
No problems at Xcode compilation time but crash when I try to launch my app on an iPhone.
Reproduction steps
In my Podfile, I change
pod 'Batch', '~> 1.21.0'
for
pod 'Batch', '~> 2.0.0'
Logs
dyld[957]: Library not loaded: @rpath/Batch.framework/Batch
Referenced from: <CEB1D1E5-FB69-3312-BB76-22708083FE33> /private/var/containers/Bundle/Application/3291B63B-EE83-47ED-8AB7-EE895CBB5BC4/MyApp.app/MyApp
Reason: tried: '/Users/me/Library/Developer/Xcode/DerivedData/MyApp-ddejunqweisyqocnsoxzgngmnpnw/Build/Products/Debug-iphoneos/PackageFrameworks/Batch.framework/Batch' (no such file), '/private/preboot/Cryptexes/OS/Users/me/Library/Developer/Xcode/DerivedData/MyApp-ddejunqweisyqocnsoxzgngmnpnw/Build/Products/Debug-iphoneos/PackageFrameworks/Batch.framework/Batch' (no such file), '/usr/lib/swift/Batch.framework/Batch' (no such file, not in dyld cache), '/private/preboot/Cryptexes/OS/usr/lib/swift/Batch.framework/Batch' (no such file), '/private/var/containers/Bundle/Application/3291B63B-EE83-47ED-8AB7-EE895CBB5BC4/MyApp.app/Frameworks/Batch.framework/Batch' (no such file), '/private/var/containers/Bundle/Application/3291B63B-EE83-47ED-8AB7-EE895CBB5BC4/MyApp.app/Frameworks/Batch.framework/Batch' (no such file), '/Users/me/Library/Developer/Xcode/DerivedData/MyApp-ddejunqweisyqocnsoxzgngmnpnw/Build/Products/Debug-iphoneos/PackageFrameworks/Batch.framework/Batch' (no such file), '/private/preboot/Cryptexes/OS/Users/me/Library/Developer/Xcode/DerivedData/MyApp-ddejunqweisyqocnsoxzgngmnpnw/Build/Products/Debug-iphoneos/PackageFrameworks/Batch.framework/Batch' (no such file), '/usr/lib/swift/Batch.framework/Batch' (no such file, not in dyld cache), '/private/preboot/Cryptexes/OS/usr/lib/swift/Batch.framework/Batch' (no such file), '/private/var/containers/Bundle/Application/3291B63B-EE83-47ED-8AB7-EE895CBB5BC4/MyApp.app/Frameworks/Batch.framework/Batch' (no such file), '/private/var/containers/Bundle/Application/3291B63B-EE83-47ED-8AB7-EE895CBB5BC4/MyApp.app/Frameworks/Batch.framework/Batch' (no such file)
Specifications
SDK Version
2.0.1
Installation method
CocoaPods
Relevant development tools versions
Xcode 15.3 (15E204a)
CocoaPods 1.15.2 (via Bundler)
Swift
swift-driver version: 1.90.11.1 Apple Swift version 5.10 (swiftlang-5.10.0.13 clang-1500.3.9.4)
Target: arm64-apple-macosx14.0
Additional information
My Podfile header
platform :ios, '15.0'
install! 'cocoapods', :warn_for_unused_master_specs_repo => false
# ignore all warnings from all pods
inhibit_all_warnings!
use_frameworks!
# Pod repositories
source 'https://cdn.cocoapods.org/'
Hi,
Is the Batch pod in your main target or is it in a framework?
2.0 became a dynamic library, so you need to make sure that the pod is linked in your main target and that Xcode knows that it must copy it on build
Hi,
Your are not in my main target and your are a xcframework (like Facebook which did the same thing as you with theirs SDKs)
But you are well declared in my relative Pods project in the same way as Facebook ones (in my example FBSDKLoginKit) and with them, I had nothing special to do in addition when I upgrade to theirs dynamic frameworks to work.
What have I missed?
I'm gonna have to try to reproduce it on my end.
In the meantime, could you try adding it to the main target? I think it's not linked because it's a transitive dependency
You could look in your app's Build phases in "Copy Frameworks" and see if FBSDKLoginKit is there and if Batch is too
Hi,
FYI you are neither defined (Batch.framework) in the ${PODS_ROOT}/Target Support Files/Pods-MyApp/Pods-MyApp-frameworks-${CONFIGURATION}-input-files.xcfilelist
${PODS_ROOT}/Target Support Files/Pods-MyApp/Pods-MyApp-frameworks.sh
...
${BUILT_PRODUCTS_DIR}/RxSwift/RxSwift.framework
${BUILT_PRODUCTS_DIR}/RxSwiftExt/RxSwiftExt.framework
${BUILT_PRODUCTS_DIR}/SQLite.swift/SQLite.framework
${BUILT_PRODUCTS_DIR}/SigmaSwiftStatistics/SigmaSwiftStatistics.framework
${BUILT_PRODUCTS_DIR}/Solar/Solar.framework
${BUILT_PRODUCTS_DIR}/Surge/Surge.framework
${BUILT_PRODUCTS_DIR}/SwiftQueue/SwiftQueue.framework
${BUILT_PRODUCTS_DIR}/SwiftyBeaver/SwiftyBeaver.framework
${BUILT_PRODUCTS_DIR}/SwiftyJSON/SwiftyJSON.framework
${BUILT_PRODUCTS_DIR}/SwiftyMarkdown/SwiftyMarkdown.framework
${BUILT_PRODUCTS_DIR}/TinyConstraints/TinyConstraints.framework
${BUILT_PRODUCTS_DIR}/Turf/Turf.framework
${BUILT_PRODUCTS_DIR}/ViewAnimator/ViewAnimator.framework
${BUILT_PRODUCTS_DIR}/YouTubePlayer/YouTubePlayer.framework
${BUILT_PRODUCTS_DIR}/lottie-ios/Lottie.framework
${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework
${PODS_XCFRAMEWORKS_BUILD_DIR}/FBAEMKit/FBAEMKit.framework/FBAEMKit
${PODS_XCFRAMEWORKS_BUILD_DIR}/FBSDKCoreKit/FBSDKCoreKit.framework/FBSDKCoreKit
${PODS_XCFRAMEWORKS_BUILD_DIR}/FBSDKCoreKit_Basics/FBSDKCoreKit_Basics.framework/FBSDKCoreKit_Basics
${PODS_XCFRAMEWORKS_BUILD_DIR}/FBSDKLoginKit/FBSDKLoginKit.framework/FBSDKLoginKit
${PODS_XCFRAMEWORKS_BUILD_DIR}/FBSDKShareKit/FBSDKShareKit.framework/FBSDKShareKit
${PODS_XCFRAMEWORKS_BUILD_DIR}/HEREMaps/NMAKit.framework/NMAKit
nor in the ${PODS_ROOT}/Target Support Files/Pods-MyApp/Pods-MyApp-frameworks-${CONFIGURATION}-output-files.xcfilelist
...
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxSwift.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxSwiftExt.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SQLite.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SigmaSwiftStatistics.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Solar.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Surge.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftQueue.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftyBeaver.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftyJSON.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftyMarkdown.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/TinyConstraints.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Turf.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ViewAnimator.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YouTubePlayer.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Lottie.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/nanopb.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBAEMKit.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBSDKCoreKit.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBSDKCoreKit_Basics.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBSDKLoginKit.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBSDKShareKit.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/NMAKit.framework
generated by my project build phase [CP] Embed Pods Frameworks unlike those from Facebook.
Thanks
I can indeed reproduce that on a clean project. I wonder why Cocoapods isn't recognizing we're a dynamic framework while it did on our private testing podspec
Perfect Let me know when you've fixed it. Thanks.
We've yet to figure out a way to tame Cocoapods. It sets up the filelist in Pods/Target Support Files/Batch , we get a Batch-xcframeworks script and it even copies it into XCFrameworkIntermediates in the DerivedData build directory, but it forgets to tell Xcode to copy the framework.
I do not understand why. I tried mimicing PSPDFKit's podspec, adding preserve_paths, moving stuff around in the zip to match facebook's, etc... Nothing works so far.
In the meantime, just telling Xcode about the framework is enough to make it copy it.
https://github.com/BatchLabs/Batch-iOS-SDK/assets/312529/fe55dd6c-2072-45f4-8453-faee0d17da8c
Note that Xcode gives a warning about "changes being made to the file will invalidate the code signature": that's a cocoapod issue. We codesign the XCFramework as recommended by Apple, but cocoapods breaks down the XCFramework into a framework for no reason during build
Hi, Maybe it is a problem with CocoaPods but by transitivity, it is a problem for you for the users who use CocoaPods to get your SDK... I pause my upgrade to 2.x for now, thanks.
We're still working on finding a fix/workaround
The issue is that CocoaPods's dynamic library detection relies on "ruby-macho". If it fails to open the framework binary, cocoapods assumes that it is a static library : https://github.com/CocoaPods/CocoaPods/blob/master/lib/cocoapods/xcode/linkage_analyzer.rb
This has the unfortunate side effect that if the library has a format that ruby-macho does not understand, the detection is broken.
I added print statements to this file, and this shows up:
MachoError for Pods/Batch/XCFrameworks/Batch.xcframework/ios-arm64/Batch.framework/Batch
Exception: Unrecognized Mach-O load command: 0x36
We don't know why we run into this. It may be because we added support for mergable libraries so that we can be used as a dynamic or static framework. It may also be that frameworks emitted by Xcode 15 with a specific configuration are not understood.
There are multiple CocoaPods issues here:
- There is no way for us in a Podspec to say that we are a dynamic library and bypass auto detection
- Cocoapods is severly out of date with its ruby-macho dependency. It is currently requiring
ruby-macho-2.5.1while ruby-macho is at version 4.0.1
We will raise an upstream issue while we debate about what our course of action is after additional testing to understand why our binary can't be parsed by their mach-o lib.
The two workarounds we have are:
- Use SPM. Even with a Flutter project, as they give you access to the Xcode project, you should be able to use SPM.
- Manually link the xcframework. This something you only have to do once, and it's better anyway as you keep the Privacy Manifest and code signature.
Upstream issue: https://github.com/CocoaPods/CocoaPods/issues/12388
We're working on a workaround. It will take a bit of time as our release pipeline isn't designed to have specific builds for package managers, only a single universal one.
Hello,
2.0.2 is out with a workaround. The CocoaPods build is no longer a mergable library nor is it codesigned due to bugs in CocoaPods.
Thanks for the report,
Hi, Thanks for the fix 👍