braze-inc / braze-swift-sdk

Braze SDK for the Apple ecosystem, including: iOS, macOS, iPadOS, visionOS, tvOS
https://www.braze.com
Other
50 stars 19 forks source link

[Bug]: Duplicate Classes when using with FirebaseRemoteConfig for Kotlin Multiplatform Project (URGENT!!!!) #122

Closed TheArchitect123 closed 5 months ago

TheArchitect123 commented 5 months ago

Platform

iOS

Platform Version

iOS 17

Braze SDK Version

5.10.1 (Latest)

Xcode Version

15.0

Computer Processor

Apple (M1)

Repro Rate

100% of the time

Steps To Reproduce

Import into your podfile 'BrazeKit' 'FirebaseRemoteConfig'

Then compile the xcode project.

Expected Behavior

That both libraries can be used at the same time without any issues.

Actual Incorrect Behavior

Compiler error comes up when building the xcode project. This happens everytime if both libraries are imported at the same time.

error: Executing of 'xcodebuild -project Pods.xcodeproj -scheme FirebaseRemoteConfig -sdk iphoneos -configuration Release' failed with code 65 and message:

Screenshot 2024-04-11 at 1 18 17 pm

Verbose Logs

REPO_ROOT="$PODS_TARGET_SRCROOT"
                "$REPO_ROOT/../gradlew" -p "$REPO_ROOT" $KOTLIN_PROJECT_PATH:syncFramework                     -Pkotlin.native.cocoapods.platform=$PLATFORM_NAME                     -Pkotlin.native.cocoapods.archs="$ARCHS"                     -Pkotlin.native.cocoapods.configuration="$CONFIGURATION"
Type-safe project accessors is an incubating feature.
> Task :xcodeVersion UP-TO-DATE
> Task :shared:checkKotlinGradlePluginConfigurationErrors
> Task :shared:generateDefApplicationInsights UP-TO-DATE
> Task :shared:podspec UP-TO-DATE
> Task :shared:podGenIos UP-TO-DATE
> Task :shared:podInstallSyntheticIos UP-TO-DATE
> Task :shared:podSetupBuildApplicationInsightsIphoneos UP-TO-DATE
> Task :shared:podBuildApplicationInsightsIphoneos UP-TO-DATE
> Task :shared:cinteropApplicationInsightsIosArm64 UP-TO-DATE
> Task :shared:generateDefDynatrace UP-TO-DATE
> Task :shared:podSetupBuildDynatraceIphoneos UP-TO-DATE
> Task :shared:podBuildDynatraceIphoneos UP-TO-DATE
> Task :shared:cinteropDynatraceIosArm64 UP-TO-DATE
> Task :shared:generateDefFBSDKCoreKit UP-TO-DATE
> Task :shared:podSetupBuildFBSDKCoreKitIphoneos UP-TO-DATE
> Task :shared:podBuildFBSDKCoreKitIphoneos UP-TO-DATE
> Task :shared:cinteropFBSDKCoreKitIosArm64 UP-TO-DATE
> Task :shared:generateDefFBSDKLoginKit UP-TO-DATE
> Task :shared:podSetupBuildFBSDKLoginKitIphoneos UP-TO-DATE
> Task :shared:podBuildFBSDKLoginKitIphoneos UP-TO-DATE
> Task :shared:cinteropFBSDKLoginKitIosArm64 UP-TO-DATE
> Task :shared:generateDefFirebaseRemoteConfig UP-TO-DATE
> Task :shared:podSetupBuildFirebaseRemoteConfigIphoneos UP-TO-DATE
> Task :shared:podBuildFirebaseRemoteConfigIphoneos FAILED
error: Executing of 'xcodebuild -project Pods.xcodeproj -scheme FirebaseRemoteConfig -sdk iphoneos -configuration Release' failed with code 65 and message: 

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':shared:podBuildFirebaseRemoteConfigIphoneos'.
> Executing of 'xcodebuild -project Pods.xcodeproj -scheme FirebaseRemoteConfig -sdk iphoneos -configuration Release' failed with code 65 and message: 

  Command line invocation:
      /Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild -project Pods.xcodeproj -scheme FirebaseRemoteConfig -sdk iphoneos -configuration Release

  User defaults from command line:
      IDEPackageSupportToolchainOverrideForManifestLoading = com.apple.dt.toolchain.XcodeDefault
      IDEPackageSupportUseBuiltinSCM = YES

  Build settings from command line:
      SDKROOT = iphoneos17.0
      TOOLCHAINS = com.apple.dt.toolchain.XcodeDefault

  ComputeTargetDependencyGraph
  note: Building targets in dependency order
  note: Target dependency graph (8 targets)
      Target 'FirebaseRemoteConfig' in project 'Pods'
          ➜ Explicit dependency on target 'FirebaseABTesting' in project 'Pods'
          ➜ Explicit dependency on target 'FirebaseCore' in project 'Pods'
          ➜ Explicit dependency on target 'FirebaseInstallations' in project 'Pods'
          ➜ Explicit dependency on target 'FirebaseSharedSwift' in project 'Pods'
          ➜ Explicit dependency on target 'GoogleUtilities' in project 'Pods'
      Target 'FirebaseSharedSwift' in project 'Pods' (no dependencies)
      Target 'FirebaseInstallations' in project 'Pods'
          ➜ Explicit dependency on target 'FirebaseCore' in project 'Pods'
          ➜ Explicit dependency on target 'GoogleUtilities' in project 'Pods'
          ➜ Explicit dependency on target 'PromisesObjC' in project 'Pods'
      Target 'FirebaseABTesting' in project 'Pods'
          ➜ Explicit dependency on target 'FirebaseCore' in project 'Pods'
      Target 'FirebaseCore' in project 'Pods'
          ➜ Explicit dependency on target 'FirebaseCoreInternal' in project 'Pods'
          ➜ Explicit dependency on target 'GoogleUtilities' in project 'Pods'
      Target 'FirebaseCoreInternal' in project 'Pods'
          ➜ Explicit dependency on target 'GoogleUtilities' in project 'Pods'
      Target 'GoogleUtilities' in project 'Pods'
          ➜ Explicit dependency on target 'PromisesObjC' in project 'Pods'
      Target 'PromisesObjC' in project 'Pods' (no dependencies)

  GatherProvisioningInputs

  CreateBuildDescription

  note: Using global toolchain override 'Xcode Default'.
  ClangStatCache /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang-stat-cache /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS17.0.sdk /Users/admin/Library/Developer/Xcode/DerivedData/SDKStatCaches.noindex/iphoneos17.0-21A325-6c9eaa8b07af4dea956ccca2a941a8b21e1d10ddc0bdcd738a98873f48b793a5.sdkstatcache
      cd /Users/admin/Documents/SharedMultiplatform/shared/build/cocoapods/synthetic/ios/Pods/Pods.xcodeproj
      /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang-stat-cache /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS17.0.sdk -o /Users/admin/Library/Developer/Xcode/DerivedData/SDKStatCaches.noindex/iphoneos17.0-21A325-6c9eaa8b07af4dea956ccca2a941a8b21e1d10ddc0bdcd738a98873f48b793a5.sdkstatcache

Additional Information

I have a firebase remote config service that fetches key/value pair data from firebase. However I can't seem to use BrazeKit at the same time without seeing this issue.

If I remove one library and keep the other, or vice versa, then it works.

jacksonemiller commented 5 months ago

Hi there,

Thank you for reporting this. I haven't been able to reproduce this in a fresh cocoapods project, so I think we'll need to take a more in depth look at this. Could you please email support@braze.com to kick off our formal internal support procedure? Having a lot more information about your xcode project and Braze integration would be very helpful here.

Thank you.

TheArchitect123 commented 5 months ago

I'm statically linking the Firebase Remote Config library. That's probably why there's a duplication issue. It looks like BrazeSDK uses FirebaseCore, and if I'm also linking FirebaseRemoteConfig (which uses Firebase core internally) then it causes the Duplication issue.

I have to statically link the libraries for performance reasons.

jacksonemiller commented 5 months ago

Hi,

I've modified my podfile to link statically and have still been unable to reproduce the issue. I think that being able to see parts of your project such as your podfile or even KMP setup might be helpful and I'd encourage you to reach out to support@braze.com so we can get some of that additional context.

Thanks.

TheArchitect123 commented 5 months ago

Since the issue exists only for iOS, here is a very specific part of the Core Module's gradle file (where the iOS Pod configuration is set)


  iosX64()
    iosArm64()
    iosSimulatorArm64()
    cocoapods {
        summary = "Some description for the Shared Module"
        homepage = "Link to the Shared Module homepage"
        version = "1.0"
        ios.deploymentTarget = "15.0"
        podfile = project.file("../sharediOS/Podfile")
        framework {
            baseName = "shared"
            isStatic = true
        }

        pod("SVProgressHUD"){
            extraOpts += listOf("-compiler-option", "-fmodules")
        }
        pod("FBSDKLoginKit"){
            extraOpts += listOf("-compiler-option", "-fmodules")
        }
        pod("FBSDKCoreKit"){
            extraOpts += listOf("-compiler-option", "-fmodules")
        }
        pod("ApplicationInsights"){
            version = "1.0-beta.8"
        }
        pod("BrazeKit") {
            extraOpts += listOf("-compiler-option", "-fmodules")
        }
        pod("SwiftRater") {
            extraOpts += listOf("-compiler-option", "-fmodules")
        }
        pod("Dynatrace") {
            extraOpts += listOf("-compiler-option", "-fmodules")
        }
    }

And here's the podfile in use for iOS (On the Xcode side):

target 'sharediOS' do
  #use_frameworks!
  inhibit_all_warnings!
  platform :ios, '15.0'
  pod 'shared', :path => '../shared'

  pod 'ApplicationInsights', '1.0-beta.8', :inhibit_warnings => true
  pod 'BrazeKit', :inhibit_warnings => true
  pod 'XCoordinator', :inhibit_warnings => true
  pod 'Toast-Swift', :inhibit_warnings => true
  pod 'MaterialComponents', :inhibit_warnings => true
  pod 'Alertift', :inhibit_warnings => true
  pod 'KRProgressHUD', :inhibit_warnings => true
  pod 'Dynatrace', :inhibit_warnings => true
  pod 'SwiftLint', :inhibit_warnings => true
  pod 'lottie-ios',:modular_headers => true, :inhibit_warnings => true
end

post_install do |installer|
 installer.pods_project.targets.each do |target|
  target.build_configurations.each do |config|
   config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '15.0'
  end
 end
end
jacksonemiller commented 5 months ago

Hi,

I can't say I'm super familiar with KMP. Some of our support engineers whose job it is to help clients with their integrations might have seen similar cases in the past. I also think that getting to see your full gradle file and other project related files could end up being very helpful.

Could I ask, is there a particular reason why BrazeKit and ApplicationInsights are listed as both iOS-specific dependencies and dependencies of the core module? (If I'm reading these files correctly.) Also, from some research online, it seems like this might be a known issue when working with static frameworks?

Thanks.

TheArchitect123 commented 5 months ago

BrazeKit and ApplicationInsights are both exposed as a Platform Services written in Kotlin. This way it keeps the source code all in Kotlin compared to having both Swift/Kotlin logic exposed as interfaces in the shared module.

Also I tried setting the library as dynamic. It doesn't fix the issue. The issue persists. I'll send the braze support team a copy of the gradle file.

And just to confirm, it's this email here? support@braze.com

jacksonemiller commented 5 months ago

Hey,

Sorry for missing this yesterday. That is the correct email. Thanks for filing this. I think it'll help move this support issue along.

Thank you.

TheArchitect123 commented 5 months ago

issue is resolved now. I just added this into top of my pod file. use_frameworks! :linkage => :static