Stripe-ios: 20.0.0 SPM build fails with undefined symbol `__llvm_profile_runtime`

Created on 15 Sep 2020  路  10Comments  路  Source: stripe/stripe-ios

Summary

I tried the new 20.0.0 release SPM support, adding the package to my project after removing it from the previous Carthage setup.
The build fails with this error:

Undefined symbols for architecture x86_64:
  "___llvm_profile_runtime", referenced from:
      ___llvm_profile_runtime_user in Stripe.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

I reported the exact same error in Segment some time ago, also testing SPM support.

Code to reproduce

Just make a new project, enable code coverage in the test scheme, and you get the issue.
Disabling code coverage completely solves the issue.

Sample project: stripe-bug.zip

iOS version

Any.

Installation method

SPM, through Xcode 12 beta 6.

SDK version

20.0.0

triaged

Most helpful comment

Based on the feedback we've received, my recommendation would be to hold off for a bit. I'll update the README.

Our current solution is to ship a static Stripe3DS2.xcframework and specify type: .dynamic in Stripe's Package.swift, which builds a dynamic Stripe.framework containing the Stripe3DS2 objects. This works in ~many situations, but fails with Code Coverage enabled.

We tried a few other options, but none of them are great:

  • Remove type: .dynamic, which would cause SPM to statically link Stripe and Stripe3DS2 into the app binary. This mostly works, but it also drops a copy of libStripe3DS2.a from the static Stripe3DS2.xcframework into the resulting app's bundle. I think this is the same bug Firebase is experiencing, which they've filed as FB8705974.
  • Remove type: .dynamic and ship a dynamic copy of Stripe3DS2.xcframework, which would statically link Stripe.framework in the app binary and dynamically link Stripe3DS2.framework. This doesn't work because of a code signing issue in Xcode 12.
  • Distribute a pre-built Stripe.xcframework binary instead of source in our Pacakge.swift. I think this would also cause the above code signing issue, though I haven't tried it yet.

All 10 comments

Thank you for reporting this, and for the repro project! We'll try to look into it soon.

The fix for Segment may not work for us:聽When I don't specify in Package.swift that we want to build a dynamic library, Xcode inexplicably copies libStripe3DS2.a into the distributed Stripe_Stripe.bundle in addition to linking it. I'm hoping this might be fixed in Xcode 12 GM.

Same issue with XCode 12 AppStore release. However adding Stripe through Cocoapods works fine.

I'm stuck between two SPM bugs:
1) SPM can't build .dynamic libraries when code coverage is enabled 鈥斅爉y guess is that Xcode isn't passing along the correct code coverage linker flags.
2) If a library isn't specified as .dynamic and it depends on a static .xcframework binaryTarget, SPM will drop a copy of the .a files from the .xcframework into the resulting app's bundle.

I'll file these with SPM soon, and we'll keep looking for a workaround.

If a library isn't specified as .dynamic and it depends on a static .xcframework binaryTarget, SPM will drop a copy of the .a files from the .xcframework into the resulting app's bundle.

@davidme-stripe was you able to find a workaround for this issue?

@davidme-stripe Thanks for working on this! We're affected by this as well. Is there an SPM bug we could track for workarounds/fixes?

What is the current recommendation from the Stripe iOS team?

Should I use SPM? I'm working on an iOS13< app on Xcode 12.

Based on the feedback we've received, my recommendation would be to hold off for a bit. I'll update the README.

Our current solution is to ship a static Stripe3DS2.xcframework and specify type: .dynamic in Stripe's Package.swift, which builds a dynamic Stripe.framework containing the Stripe3DS2 objects. This works in ~many situations, but fails with Code Coverage enabled.

We tried a few other options, but none of them are great:

  • Remove type: .dynamic, which would cause SPM to statically link Stripe and Stripe3DS2 into the app binary. This mostly works, but it also drops a copy of libStripe3DS2.a from the static Stripe3DS2.xcframework into the resulting app's bundle. I think this is the same bug Firebase is experiencing, which they've filed as FB8705974.
  • Remove type: .dynamic and ship a dynamic copy of Stripe3DS2.xcframework, which would statically link Stripe.framework in the app binary and dynamically link Stripe3DS2.framework. This doesn't work because of a code signing issue in Xcode 12.
  • Distribute a pre-built Stripe.xcframework binary instead of source in our Pacakge.swift. I think this would also cause the above code signing issue, though I haven't tried it yet.

It doesn't look like Xcode will be fixed in the near future, so I'm going to try option 2. If you build SPM against the dynamic-xcframework branch and use the workaround at https://pspdfkit.com/guides/ios/current/knowledge-base/library-not-found-swiftpm/, it should resolve this issue. After switching branches, you'll also have to remove and re-add the Stripe dependency in the Frameworks, Libraries, and Embedded Content section of your target settings.

Please try Stripe 20.1.0, it should fix this. Note that you'll have to remove and re-add Stripe from the Frameworks, Libraries, and Embedded Content section of your target's settings after updating, and you'll need to apply a code-signing workaround until Xcode 12.2 is out.

Hi all! The Stripe3DS2 dependency is now distributed as source instead of a binary, which should allow everyone to remove all their framework hacks. Please update to version 21.2.0.

Was this page helpful?
0 / 5 - 0 ratings