Cocoapods: Duplicate symbols when framework target has a static dependency

Created on 11 Oct 2017  路  31Comments  路  Source: CocoaPods/CocoaPods

Report

What did you do?

I have a project with two targets A and B. Target A is an iOS app, target B is a dynamic iOS framework. Both targets need FirebaseAnalytics dependency (which to my understanding is a static vendored library).

What did you expect to happen?

Have a correctly linked project where static dependencies of target B would be only present in target A's binary.

What happened instead?

No matter how I try to add the dependency, there are always two possible outcomes. One is that it compiles and runs, but all symbols from FirebaseAnalytics are reported to be duplicates contained in both target A and B. If I manually change the target A's xcconfig file (generated by CocoaPods) and remove -framework FirebaseAnalytics from OTHER_LDFLAGS it seems to work as expected.

The other outcome are just No such module 'FirebaseAnalytics' errors. That can be achieved by changing the Podfile to this:

platform :ios, '9.0'
use_frameworks!

abstract_target 'ProjectRoot' do
    pod 'FirebaseAnalytics'

    target 'SampleApp' do

      pod 'AFNetworking'
    end

    target 'SampleFramework' do
        inherit! :search_paths
      pod 'CocoaLumberjack'
    end

end

CocoaPods Environment

I tried both CocoaPods 1.3.1 and 1.4.0.beta.1. The following environment dump is from 1.3.1.

Stack

   CocoaPods : 1.3.1
        Ruby : ruby 2.2.1p85 (2015-02-26 revision 49769) [x86_64-darwin14]
    RubyGems : 2.6.7
        Host : Mac OS X 10.12.6 (16G29)
       Xcode : 9.0 (9A235)
         Git : git version 2.13.5 (Apple Git-94)
Ruby lib dir : /Users/TadeasKriz/.rvm/rubies/ruby-2.2.1/lib
Repositories : master - https://github.com/CocoaPods/Specs.git @ 2aff79c74df623306725ab10122c62017088a5e3

Installation Source

Executable Path: /Users/TadeasKriz/.rvm/gems/ruby-2.2.1/bin/pod

Plugins

cocoapods-acknowledgements : 1.0.0
cocoapods-clean            : 0.0.1
cocoapods-deintegrate      : 1.0.1
cocoapods-dependencies     : 1.0.0
cocoapods-plugins          : 1.0.0
cocoapods-release          : 0.3.1
cocoapods-search           : 1.0.0
cocoapods-stats            : 1.0.0
cocoapods-superdeintegrate : 0.0.1
cocoapods-trunk            : 1.2.0
cocoapods-try              : 1.1.0
cocoapods-wholemodule      : 0.0.1

Podfile

platform :ios, '9.0'
use_frameworks!

target 'SampleApp' do

  pod 'AFNetworking'
end

target 'SampleFramework' do
  pod 'CocoaLumberjack'
  pod 'FirebaseAnalytics'
end

Project that demonstrates the issue

I created a sample project to show this: https://github.com/TadeasKriz/CocoaPodsStaticDependencyError (it's based on @benasher44's https://github.com/benasher44/CocoaPodsLibExample).

awaiting input

Most helpful comment

I have a new version of the workaround. It works when some static libraries are only used in the Application target, but not in the library target. Still not sure if it's a good idea to use this, but at this time we don't have much else to try.

post_install do |installer|
    applicationTargets = [
        'Pods-SampleApp',
    ]
    libraryTargets = [
        'Pods-SampleLib',
    ]

    embedded_targets = installer.aggregate_targets.select { |aggregate_target|
        libraryTargets.include? aggregate_target.name
    }
    embedded_pod_targets = embedded_targets.flat_map { |embedded_target| embedded_target.pod_targets }
    host_targets = installer.aggregate_targets.select { |aggregate_target|
        applicationTargets.include? aggregate_target.name
    }

    # We only want to remove pods from Application targets, not libraries
    host_targets.each do |host_target|
        host_target.xcconfigs.each do |config_name, config_file|
            host_target.pod_targets.each do |pod_target|
                if embedded_pod_targets.include? pod_target
                    pod_target.specs.each do |spec|
                        if spec.attributes_hash['ios'] != nil
                            frameworkPaths = spec.attributes_hash['ios']['vendored_frameworks']
                            else
                            frameworkPaths = spec.attributes_hash['vendored_frameworks']
                        end
                        if frameworkPaths != nil
                            frameworkNames = Array(frameworkPaths).map(&:to_s).map do |filename|
                                extension = File.extname filename
                                File.basename filename, extension
                            end
                            frameworkNames.each do |name|
                                puts "Removing #{name} from OTHER_LDFLAGS of target #{host_target.name}"
                                config_file.frameworks.delete(name)
                            end
                        end
                    end
                end
            end
            xcconfig_path = host_target.xcconfig_path(config_name)
            config_file.save_as(xcconfig_path)
        end
    end
end

All 31 comments

FirebaseAnalytics is a static library framework and the iOS linker does not support static library dependencies for dynamic libraries.

One approach would be to make SampleFramework a static library framework as well with a CocoaPod static_framework with the feature introduced in 1.4.0 in #6811

@paulb777 Thanks for the info, I'll try to look for a way to use it differently.

Also, I made this stupid workaround, but it does seem to do the trick.

post_install do |installer|
    installer.aggregate_targets.each do |aggregate_target|
        if aggregate_target.name == 'Pods-SampleApp'
            aggregate_target.xcconfigs.each do |config_name, config_file|
                aggregate_target.pod_targets.each do |pod_target|
                    pod_target.specs.each do |spec|
                        if spec.attributes_hash['vendored_frameworks'] != nil or (spec.attributes_hash['ios'] != nil and spec.attributes_hash['ios']['vendored_frameworks'] != nil)
                            puts "Removing #{spec.name}"
                            config_file.frameworks.delete(spec.name)
                        end
                    end
                end
                xcconfig_path = aggregate_target.xcconfig_path(config_name)
                config_file.save_as(xcconfig_path)
            end
        end
    end
end

@TadeasKriz you are the man, I was on the same issue since hours... Your workaround worked for me as I can build my app, thanks. I still have some warnings in the console but way less than before.
I didn't figure yet why:

objc[5193]: Class FIRClearcutWriter is implemented in both /private/var/containers/Bundle/Application/39FF9BB6-E9CC-4AEE-8173-CC3C1B3133C1/BabySittor.app/Frameworks/BabysittorKit.framework/BabysittorKit (0x105e48160) and /var/containers/Bundle/Application/39FF9BB6-E9CC-4AEE-8173-CC3C1B3133C1/BabySittor.app/BabySittor (0x102c65cd0). One of the two will be used. Which one is undefined. objc[5193]: Class FIRClearcutAccountData is implemented in both /private/var/containers/Bundle/Application/39FF9BB6-E9CC-4AEE-8173-CC3C1B3133C1/BabySittor.app/Frameworks/BabysittorKit.framework/BabysittorKit (0x105e481b0) and /var/containers/Bundle/Application/39FF9BB6-E9CC-4AEE-8173-CC3C1B3133C1/BabySittor.app/BabySittor (0x102c65d20). One of the two will be used. Which one is undefined. objc[5193]: Class FIRClearcutRequest is implemented in both /private/var/containers/Bundle/Application/39FF9BB6-E9CC-4AEE-8173-CC3C1B3133C1/BabySittor.app/Frameworks/BabysittorKit.framework/BabysittorKit (0x105e48200) and /var/containers/Bundle/Application/39FF9BB6-E9CC-4AEE-8173-CC3C1B3133C1/BabySittor.app/BabySittor (0x102c65d70). One of the two will be used. Which one is undefined. objc[5193]: Class FIRClearcutLogger is implemented in both /private/var/containers/Bundle/Application/39FF9BB6-E9CC-4AEE-8173-CC3C1B3133C1/BabySittor.app/Frameworks/BabysittorKit.framework/BabysittorKit (0x105e48250) and /var/containers/Bundle/Application/39FF9BB6-E9CC-4AEE-8173-CC3C1B3133C1/BabySittor.app/BabySittor (0x102c65dc0). One of the two will be used. Which one is undefined. objc[5193]: Class FIRDiagnostics is implemented in both /private/var/containers/Bundle/Application/39FF9BB6-E9CC-4AEE-8173-CC3C1B3133C1/BabySittor.app/Frameworks/BabysittorKit.framework/BabysittorKit (0x105e482a0) and /var/containers/Bundle/Application/39FF9BB6-E9CC-4AEE-8173-CC3C1B3133C1/BabySittor.app/BabySittor (0x102c65e10). One of the two will be used. Which one is undefined. objc[5193]: Class CLRPBClientInfo is implemented in both /private/var/containers/Bundle/Application/39FF9BB6-E9CC-4AEE-8173-CC3C1B3133C1/BabySittor.app/Frameworks/BabysittorKit.framework/BabysittorKit (0x105e482f0) and /var/containers/Bundle/Application/39FF9BB6-E9CC-4AEE-8173-CC3C1B3133C1/BabySittor.app/BabySittor (0x102c65e60). One of the two will be used. Which one is undefined. objc[5193]: Class CLRPBIosClientInfo is implemented in both /private/var/containers/Bundle/Application/39FF9BB6-E9CC-4AEE-8173-CC3C1B3133C1/BabySittor.app/Frameworks/BabysittorKit.framework/BabysittorKit (0x105e48340) and /var/containers/Bundle/Application/39FF9BB6-E9CC-4AEE-8173-CC3C1B3133C1/BabySittor.app/BabySittor (0x102c65eb0). One of the two will be used. Which one is undefined. objc[5193]: Class CLRPBLogEvent is implemented in both /private/var/containers/Bundle/Application/39FF9BB6-E9CC-4AEE-8173-CC3C1B3133C1/BabySittor.app/Frameworks/BabysittorKit.framework/BabysittorKit (0x105e48390) and /var/containers/Bundle/Application/39FF9BB6-E9CC-4AEE-8173-CC3C1B3133C1/BabySittor.app/BabySittor (0x102c65f00). One of the two will be used. Which one is undefined. objc[5193]: Class CLRPBLogRequest is implemented in both /private/var/containers/Bundle/Application/39FF9BB6-E9CC-4AEE-8173-CC3C1B3133C1/BabySittor.app/Frameworks/BabysittorKit.framework/BabysittorKit (0x105e483e0) and /var/containers/Bundle/Application/39FF9BB6-E9CC-4AEE-8173-CC3C1B3133C1/BabySittor.app/BabySittor (0x102c65f50). One of the two will be used. Which one is undefined. objc[5193]: Class FIRPBErrorInfo is implemented in both /private/var/containers/Bundle/Application/39FF9BB6-E9CC-4AEE-8173-CC3C1B3133C1/BabySittor.app/Frameworks/BabysittorKit.framework/BabysittorKit (0x105e48430) and /var/containers/Bundle/Application/39FF9BB6-E9CC-4AEE-8173-CC3C1B3133C1/BabySittor.app/BabySittor (0x102c65fa0). One of the two will be used. Which one is undefined. objc[5193]: Class FIRPBICoreConfiguration is implemented in both /private/var/containers/Bundle/Application/39FF9BB6-E9CC-4AEE-8173-CC3C1B3133C1/BabySittor.app/Frameworks/BabysittorKit.framework/BabysittorKit (0x105e48480) and /var/containers/Bundle/Application/39FF9BB6-E9CC-4AEE-8173-CC3C1B3133C1/BabySittor.app/BabySittor

@TadeasKriz Be careful. The build error workaround is potentially pushing bugs to runtime where duplicate implementations can cause subtle incorrect behavior.

@paulb777 With this workaround I don't see any warnings about duplicate implementations. I'm not sure why @loryhuz does. I might have missed something to look for (maybe another property instead of vendored_frameworks).

My question is, if I get no warnings about duplicate implementations, do I have them? I thought that this workaround will tell the linker to not link static libraries to the iOS app target (leaving them linked only to the library). Is this assumption wrong? Thank you for your insight.

@paulb777 I've checked again, I still have like 3 warnings about duplicates (way way less than before and now the app started working as expected). I think that's because of the way I try to "detect" whether the library is static. Do you know any other way to tell if the dependency is a static library framework in the post_install? Thanks.

I see it now. In some cases I'm removing wrong framework names. I need to remove them by the vendored framework name, not by the spec name.

@loryhuz I'll update the workaround in a few minutes. Still would love to find a better solution though.

@loryhuz New version of the workaround, this time you shouldn't see any warnings about duplicate symbols.

post_install do |installer|
    installer.aggregate_targets.each do |aggregate_target|
        puts aggregate_target.name
        if aggregate_target.name == 'Pods-SampleApp'
            aggregate_target.xcconfigs.each do |config_name, config_file|
                aggregate_target.pod_targets.each do |pod_target|
                    pod_target.specs.each do |spec|
                        if spec.attributes_hash['ios'] != nil
                            frameworkPaths = spec.attributes_hash['ios']['vendored_frameworks']
                        else
                            frameworkPaths = spec.attributes_hash['vendored_frameworks']
                        end
                        if frameworkPaths != nil
                            frameworkNames = Array(frameworkPaths).map(&:to_s).map do |filename|
                                extension = File.extname filename
                                File.basename filename, extension
                            end
                            frameworkNames.each do |name|
                                puts "Removing #{name} from OTHER_LDFLAGS"
                                config_file.frameworks.delete(name)
                            end
                        end
                    end
                end
                xcconfig_path = aggregate_target.xcconfig_path(config_name)
                config_file.save_as(xcconfig_path)
            end
        end
    end
end

@TadeasKriz Thanks for the help in this issue. This one seems more hard ! I can't compile with your new workaround, it's seems it's related to other static dependencies I have in my Podfile (like Facebook SDK), since I didn't see undefined symbols errors for Firebase:

Undefined symbols for architecture arm64:
"_OBJC_CLASS_$_FBSDKClass", referenced from:
objc-class-ref in ViewController.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

What dependency is the FBSDKClass from? My guess is they use vendored_frameworks as well, but the framework is not a static library one, but dynamic.

I put this class as an example, but here is the full trace with real class names:

d: warning: Auto-Linking supplied '/Users/loryhuz/Documents/BabySittor/Pods/ZDCChat/ZDCChat.framework/ZDCChat', framework linker option at /Users/loryhuz/Documents/BabySittor/Pods/ZDCChat/ZDCChat.framework/ZDCChat is not a dylib
ld: warning: Auto-Linking supplied '/Users/loryhuz/Documents/BabySittor/Pods/ZDCChat/ZDCChatAPI.framework/ZDCChatAPI', framework linker option at /Users/loryhuz/Documents/BabySittor/Pods/ZDCChat/ZDCChatAPI.framework/ZDCChatAPI is not a dylib
ld: warning: Auto-Linking supplied '/Users/loryhuz/Documents/BabySittor/Pods/AccountKit/AccountKit.framework/AccountKit', framework linker option at /Users/loryhuz/Documents/BabySittor/Pods/AccountKit/AccountKit.framework/AccountKit is not a dylib
ld: warning: Auto-Linking supplied '/Users/loryhuz/Documents/BabySittor/Pods/Fabric/iOS/Fabric.framework/Fabric', framework linker option at /Users/loryhuz/Documents/BabySittor/Pods/Fabric/iOS/Fabric.framework/Fabric is not a dylib
Undefined symbols for architecture arm64:
"_OBJC_CLASS_$_ZDCRatingCell", referenced from:
objc-class-ref in SettingsViewController.o
"_OBJC_CLASS_$_ZDCVisitorChatCell", referenced from:
objc-class-ref in SettingsViewController.o
"_OBJC_CLASS_$_ZDCAgentChatCell", referenced from:
objc-class-ref in SettingsViewController.o
"_OBJC_CLASS_$_ZDCChat", referenced from:
objc-class-ref in SettingsViewController.o
objc-class-ref in AppDelegate.o
ld: symbol(s) not found for architecture arm64

And about this pod:
https://github.com/zendesk/zendesk_sdk_chat_ios
I didn't understand as I only reference it in my main app target, not in my Framework. I thought your post_install hook was only removing pod reference in the top of the file (abstract_target) to avoid duplicate but it's a total another stuff I guess ?

It was removing all of them. It's probably a good idea to somehow check if they are in the framework as well, that didn't occur to me before. Let me check that.

@loryhuz Alright, try this one:

post_install do |installer|
    sharedLibrary = installer.aggregate_targets.find { |aggregate_target| aggregate_target.name == 'Pods-SampleFramework' }
    installer.aggregate_targets.each do |aggregate_target|
        if aggregate_target.name == 'Pods-SampleApp'
            aggregate_target.xcconfigs.each do |config_name, config_file|
                sharedLibraryPodTargets = sharedLibrary.pod_targets
                aggregate_target.pod_targets.select { |pod_target| sharedLibraryPodTargets.include?(pod_target) }.each do |pod_target|
                    pod_target.specs.each do |spec|
                        frameworkPaths = unless spec.attributes_hash['ios'].nil? then spec.attributes_hash['ios']['vendored_frameworks'] else spec.attributes_hash['vendored_frameworks'] end || Set.new
                        frameworkNames = Array(frameworkPaths).map(&:to_s).map do |filename|
                            extension = File.extname filename
                            File.basename filename, extension
                        end
                        frameworkNames.each do |name|
                            puts "Removing #{name} from OTHER_LDFLAGS"
                            config_file.frameworks.delete(name)
                        end
                    end
                end
                xcconfig_path = aggregate_target.xcconfig_path(config_name)
                config_file.save_as(xcconfig_path)
            end
        end
    end
end

@TadeasKriz Well done ! Console warnings completely disappeared now. I still have two linker warnings with this one:

ld: warning: Auto-Linking supplied 'xxx/Pods/Fabric/iOS/Fabric.framework/Fabric', framework linker option at xxx/BabySittor/Pods/Fabric/iOS/Fabric.framework/Fabric is not a dylib
ld: warning: Auto-Linking supplied 'xxx/Pods/AccountKit/AccountKit.framework/AccountKit', framework linker option at xxx/Pods/AccountKit/AccountKit.framework/AccountKit is not a dylib

Dunno why I got them

@loryhuz I have the exact same warning.

ld: warning: Auto-Linking supplied 'xxx/Pods/Fabric/iOS/Fabric.framework/Fabric', framework linker option at xxx/Pods/Fabric/iOS/Fabric.framework/Fabric is not a dylib

Here is my podfile:

platform :ios, '10.0'
use_frameworks!
target 'xxxCore' do
    pod 'Fabric', '~> 1.6.13'
    pod 'Crashlytics', '~> 3.8.6'
    target 'xxx' do
        inherit! :search_paths
    end
end

Did you manage to fix this warning?

yes @adauguet follow the workaround script (post_install)

There hasn't been any activity on this issue recently. Due to the high number of incoming GitHub notifications, we have to clean some of the old issues, as many of them have already been resolved with the latest updates.

This issue will be auto-closed because there hasn't been any activity for a few months. Feel free to open a new one if you still experience this problem :+1:

Posting the workaround that I'm currently using in case it's helpful to anyone. This workaround uses the pre_install hook instead of the post_install hook. The issue occurs in the analyzer which runs before the pre_install hook. So you only have to change one thing if you make the change there. Using the example from https://github.com/CocoaPods/CocoaPods/issues/7126#issue-264583808, add the following to your Podfile.

pre_install do |installer|
  embedded_target = installer.aggregate_targets.find { |aggregate_target| aggregate_target.name == 'Pods-SampleFramework' }
  host_target = installer.aggregate_targets.find { |aggregate_target| aggregate_target.name == 'Pods-SampleApp' }
  host_target.pod_targets = host_target.pod_targets - embedded_target.pod_targets
end

Please let me know if you notice any potential issues with my workaround.

Related issues:

@hongrich Hi
In the example below AFNetworking also will be removed, that's not right.

platform :ios, '9.0'
use_frameworks!

target 'SampleApp' do
  pod 'AFNetworking'
end

target 'SampleFramework' do
  pod 'CocoaLumberjack'
  pod 'FirebaseAnalytics'
  pod 'AFNetworking'
end

I get a lots of similar warning on app start.
I start with @TadeasKriz 's solution, but does not disappeared all of my warnings.

I want to use 'couchbase-lite-ios', '~> 1.4.1', this pod contains an CBLJSViewCompiler.a file, what linked into my core lib, and into the main app.
A resolve it with edit @TadeasKriz 's code, with insert a remove for CBLJSViewCompiler.afile bellow.

post_install do |installer|
    sharedLibrary = installer.aggregate_targets.find { |aggregate_target| aggregate_target.name == 'Pods-SampleFramework' }
    installer.aggregate_targets.each do |aggregate_target|
        if aggregate_target.name == 'Pods-SampleApp'
            aggregate_target.xcconfigs.each do |config_name, config_file|
                sharedLibraryPodTargets = sharedLibrary.pod_targets
                aggregate_target.pod_targets.select { |pod_target| sharedLibraryPodTargets.include?(pod_target) }.each do |pod_target|
                    pod_target.specs.each do |spec|
                        frameworkPaths = unless spec.attributes_hash['ios'].nil? then spec.attributes_hash['ios']['vendored_frameworks'] else spec.attributes_hash['vendored_frameworks'] end || Set.new
                        frameworkNames = Array(frameworkPaths).map(&:to_s).map do |filename|
                            extension = File.extname filename
                            File.basename filename, extension
                        end
                        frameworkNames.each do |name|
                            puts "Removing #{name} from OTHER_LDFLAGS"
                            config_file.frameworks.delete(name)
                            config_file.libraries.delete("CBLJSViewCompiler")#<- What I insert
                        end
                    end
                end
                xcconfig_path = aggregate_target.xcconfig_path(config_name)
                config_file.save_as(xcconfig_path)
            end
        end
    end
end

@hongrich Hi,
I have dependencies like :

    pod 'Firebase/Core'
    pod 'FirebaseUI/Auth'
    pod 'FirebaseUI/Google'
    pod 'FirebaseUI/Facebook'
    pod 'FirebaseUI/Phone'
    pod 'Firebase/Storage'
    pod 'FBSDKLoginKit'

and your workaround give me this error:

dyld: Library not loaded: @rpath/Bolts.framework/Bolts
  Referenced from: /.../SampleFramework
  Reason: image not found

Any idea?

I have a new version of the workaround. It works when some static libraries are only used in the Application target, but not in the library target. Still not sure if it's a good idea to use this, but at this time we don't have much else to try.

post_install do |installer|
    applicationTargets = [
        'Pods-SampleApp',
    ]
    libraryTargets = [
        'Pods-SampleLib',
    ]

    embedded_targets = installer.aggregate_targets.select { |aggregate_target|
        libraryTargets.include? aggregate_target.name
    }
    embedded_pod_targets = embedded_targets.flat_map { |embedded_target| embedded_target.pod_targets }
    host_targets = installer.aggregate_targets.select { |aggregate_target|
        applicationTargets.include? aggregate_target.name
    }

    # We only want to remove pods from Application targets, not libraries
    host_targets.each do |host_target|
        host_target.xcconfigs.each do |config_name, config_file|
            host_target.pod_targets.each do |pod_target|
                if embedded_pod_targets.include? pod_target
                    pod_target.specs.each do |spec|
                        if spec.attributes_hash['ios'] != nil
                            frameworkPaths = spec.attributes_hash['ios']['vendored_frameworks']
                            else
                            frameworkPaths = spec.attributes_hash['vendored_frameworks']
                        end
                        if frameworkPaths != nil
                            frameworkNames = Array(frameworkPaths).map(&:to_s).map do |filename|
                                extension = File.extname filename
                                File.basename filename, extension
                            end
                            frameworkNames.each do |name|
                                puts "Removing #{name} from OTHER_LDFLAGS of target #{host_target.name}"
                                config_file.frameworks.delete(name)
                            end
                        end
                    end
                end
            end
            xcconfig_path = host_target.xcconfig_path(config_name)
            config_file.save_as(xcconfig_path)
        end
    end
end

@TadeasKriz to implement this in my own project I assume I replace Pods-SampleApp with my app name and Pods-SampleLib with a library name and list all of them I want this to apply to?

I tried to insert the postinstall code, but I get:

[!] An error occurred while processing the post-install hook of the Podfile.
undefined method `build_configurations' for nil:NilClass

See also the next comment.

This is the error that I am getting when I run the app:

objc[99263]: Class PodsDummy_CocoaAsyncSocket is implemented in both /Users/user172615/Library/Developer/CoreSimulator/Devices/B4BCD2F3-8787-4F77-AA76-5DB45FA2EA7C/data/Containers/Bundle/Application/1E01783C-C884-4F5B-A253-28CF8E0E8C55/testProject.app/Frameworks/SquareReaderSDK.framework/SquareReaderSDK (0x110866c90) and /Users/user172615/Library/Developer/CoreSimulator/Devices/B4BCD2F3-8787-4F77-AA76-5DB45FA2EA7C/data/Containers/Bundle/Application/1E01783C-C884-4F5B-A253-28CF8E0E8C55/testProject.app/testProject (0x10c764238). One of the two will be used. Which one is undefined.

podfile after the change ('start of change' and 'end of change' mark the added lines):

platform :ios, '11.1'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'

def add_flipper_pods!(versions = {})
  versions['Flipper'] ||= '~> 0.33.1'
  versions['DoubleConversion'] ||= '1.1.7'
  versions['Flipper-Folly'] ||= '~> 2.1'
  versions['Flipper-Glog'] ||= '0.3.6'
  versions['Flipper-PeerTalk'] ||= '~> 0.0.4'
  versions['Flipper-RSocket'] ||= '~> 1.0'

  pod 'FlipperKit', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/FlipperKitLayoutPlugin', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/SKIOSNetworkPlugin', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/FlipperKitUserDefaultsPlugin', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/FlipperKitReactPlugin', versions['Flipper'], :configuration => 'Debug'

  # List all transitive dependencies for FlipperKit pods
  # to avoid them being linked in Release builds
  pod 'Flipper', versions['Flipper'], :configuration => 'Debug'
  pod 'Flipper-DoubleConversion', versions['DoubleConversion'], :configuration => 'Debug'
  pod 'Flipper-Folly', versions['Flipper-Folly'], :configuration => 'Debug'
  pod 'Flipper-Glog', versions['Flipper-Glog'], :configuration => 'Debug'
  pod 'Flipper-PeerTalk', versions['Flipper-PeerTalk'], :configuration => 'Debug'
  pod 'Flipper-RSocket', versions['Flipper-RSocket'], :configuration => 'Debug'
  pod 'FlipperKit/Core', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/CppBridge', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/FBCxxFollyDynamicConvert', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/FBDefines', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/FKPortForwarding', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/FlipperKitHighlightOverlay', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/FlipperKitLayoutTextSearchable', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/FlipperKitNetworkPlugin', versions['Flipper'], :configuration => 'Debug'
end

# Post Install processing for Flipper
def flipper_post_install(installer)
  installer.pods_project.targets.each do |target|
    if target.name == 'YogaKit'
      target.build_configurations.each do |config|
        config.build_settings['SWIFT_VERSION'] = '4.1'
      end
    end
  end
end

target 'testProject' do
  # Pods for testProject
  pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector"
  pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec"
  pod 'RCTRequired', :path => "../node_modules/react-native/Libraries/RCTRequired"
  pod 'RCTTypeSafety', :path => "../node_modules/react-native/Libraries/TypeSafety"
  pod 'React', :path => '../node_modules/react-native/'
  pod 'React-Core', :path => '../node_modules/react-native/'
  pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules'
  pod 'React-Core/DevSupport', :path => '../node_modules/react-native/'
  pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS'
  pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation'
  pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob'
  pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image'
  pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS'
  pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network'
  pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings'
  pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text'
  pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration'
  pod 'React-Core/RCTWebSocket', :path => '../node_modules/react-native/'

  pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact'
  pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi'
  pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor'
  pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector'
  pod 'ReactCommon/callinvoker', :path => "../node_modules/react-native/ReactCommon"
  pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon"
  pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga', :modular_headers => true

  pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
  pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
  pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'

  target 'testProjectTests' do
    inherit! :complete
    # Pods for testing
  end

  use_native_modules!

  # Enables Flipper.
  #
  # Note that if you have use_frameworks! enabled, Flipper will not work and
  # you should disable these next few lines.
  add_flipper_pods!

  post_install do |installer|
      flipper_post_install(installer)
    # ---------- start of change ------------
    sharedLibrary = installer.aggregate_targets.find { |aggregate_target| aggregate_target.name == 'Pods-SquareReaderSDK' }
    installer.aggregate_targets.each do |aggregate_target|
        if aggregate_target.name == 'Pods-plumpPlym'
            aggregate_target.xcconfigs.each do |config_name, config_file|
                sharedLibraryPodTargets = sharedLibrary.pod_targets
                aggregate_target.pod_targets.select { |pod_target| sharedLibraryPodTargets.include?(pod_target) }.each do |pod_target|
                    pod_target.specs.each do |spec|
                        frameworkPaths = unless spec.attributes_hash['ios'].nil? then spec.attributes_hash['ios']['vendored_frameworks'] else spec.attributes_hash['vendored_frameworks'] end || Set.new
                        frameworkNames = Array(frameworkPaths).map(&:to_s).map do |filename|
                            extension = File.extname filename
                            File.basename filename, extension
                        end
                    end
                    frameworkNames.each do |name|
                        if name != 'SquareReaderSDK'
                            raise("Script is trying to remove unwanted flags: #{name}. Check it out!")
                        end
                        puts "Removing #{name} from OTHER_LDFLAGS"
                        config_file.frameworks.delete(name)
                    end
                end
            end
            xcconfig_path = aggregate_target.xcconfig_path(config_name)
            config_file.save_as(xcconfig_path)
        end
    end
   # ---------- end of change ------------
end


end

target 'testProject-tvOS' do
  # Pods for testProject-tvOS

  target 'testProject-tvOSTests' do
    inherit! :search_paths
    # Pods for testing
  end
end

The following is another trial, following the code example in https://stackoverflow.com/a/52773670/5532513:

platform :ios, '11.1'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'

def add_flipper_pods!(versions = {})
  versions['Flipper'] ||= '~> 0.33.1'
  versions['DoubleConversion'] ||= '1.1.7'
  versions['Flipper-Folly'] ||= '~> 2.1'
  versions['Flipper-Glog'] ||= '0.3.6'
  versions['Flipper-PeerTalk'] ||= '~> 0.0.4'
  versions['Flipper-RSocket'] ||= '~> 1.0'

  pod 'FlipperKit', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/FlipperKitLayoutPlugin', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/SKIOSNetworkPlugin', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/FlipperKitUserDefaultsPlugin', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/FlipperKitReactPlugin', versions['Flipper'], :configuration => 'Debug'

  # List all transitive dependencies for FlipperKit pods
  # to avoid them being linked in Release builds
  pod 'Flipper', versions['Flipper'], :configuration => 'Debug'
  pod 'Flipper-DoubleConversion', versions['DoubleConversion'], :configuration => 'Debug'
  pod 'Flipper-Folly', versions['Flipper-Folly'], :configuration => 'Debug'
  pod 'Flipper-Glog', versions['Flipper-Glog'], :configuration => 'Debug'
  pod 'Flipper-PeerTalk', versions['Flipper-PeerTalk'], :configuration => 'Debug'
  pod 'Flipper-RSocket', versions['Flipper-RSocket'], :configuration => 'Debug'
  pod 'FlipperKit/Core', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/CppBridge', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/FBCxxFollyDynamicConvert', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/FBDefines', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/FKPortForwarding', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/FlipperKitHighlightOverlay', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/FlipperKitLayoutTextSearchable', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/FlipperKitNetworkPlugin', versions['Flipper'], :configuration => 'Debug'
end

# Post Install processing for Flipper
def flipper_post_install(installer)
  installer.pods_project.targets.each do |target|
    if target.name == 'YogaKit'
      target.build_configurations.each do |config|
        config.build_settings['SWIFT_VERSION'] = '4.1'
      end
    end
  end
end

target 'testProject' do
  # Pods for testProject
  pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector"
  pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec"
  pod 'RCTRequired', :path => "../node_modules/react-native/Libraries/RCTRequired"
  pod 'RCTTypeSafety', :path => "../node_modules/react-native/Libraries/TypeSafety"
  pod 'React', :path => '../node_modules/react-native/'
  pod 'React-Core', :path => '../node_modules/react-native/'
  pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules'
  pod 'React-Core/DevSupport', :path => '../node_modules/react-native/'
  pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS'
  pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation'
  pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob'
  pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image'
  pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS'
  pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network'
  pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings'
  pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text'
  pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration'
  pod 'React-Core/RCTWebSocket', :path => '../node_modules/react-native/'

  pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact'
  pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi'
  pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor'
  pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector'
  pod 'ReactCommon/callinvoker', :path => "../node_modules/react-native/ReactCommon"
  pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon"
  pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga', :modular_headers => true

  pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
  pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
  pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'

  target 'testProjectTests' do
    inherit! :complete
    # Pods for testing
  end

  use_native_modules!

  # Enables Flipper.
  #
  # Note that if you have use_frameworks! enabled, Flipper will not work and
  # you should disable these next few lines.
  add_flipper_pods!


post_install do |installer|
  flipper_post_install(installer)
  # ---------- start of change ------------
  # you should change the sample auto_process_target method call to fit your project

  # sample for the question
  auto_process_target('testProject', 'SquareReaderSDK', installer)
  # sample for the multi app use on same framework
  #auto_process_target(['exampleiOSApp', 'exampleMacApp'], 'exampleFramework', installer)

end

# the below code no need to modify

def auto_process_target(app_target_names, embedded_target_name, installer)
  words = find_words_at_embedded_target('Pods-' + embedded_target_name,
                                        installer)
  handle_app_targets(app_target_names.map{ |str| 'Pods-' + str },
                     words,
                     installer)
end

def find_line_with_start(str, start)
  str.each_line do |line|
      if line.start_with?(start)
        return line
      end
  end
  return nil
end

def remove_words(str, words)
  new_str = str
  words.each do |word|
    new_str = new_str.sub(word, '')
  end
  return new_str
end

def find_words_at_embedded_target(target_name, installer)
  target = installer.pods_project.targets.find { |target| target.name == target_name }
  target.build_configurations.each do |config|
    xcconfig_path = config.base_configuration_reference.real_path
    xcconfig = File.read(xcconfig_path)
    old_line = find_line_with_start(xcconfig, "OTHER_LDFLAGS")

    if old_line == nil
      next
    end
    words = old_line.split(' ').select{ |str| str.start_with?("-l") }.map{ |str| ' ' + str }
    return words
  end
end

def handle_app_targets(names, words, installer)
  installer.pods_project.targets.each do |target|
    if names.index(target.name) == nil
      next
    end
    puts "Updating #{target.name} OTHER_LDFLAGS"
    target.build_configurations.each do |config|
      xcconfig_path = config.base_configuration_reference.real_path
      xcconfig = File.read(xcconfig_path)
      old_line = find_line_with_start(xcconfig, "OTHER_LDFLAGS")

      if old_line == nil
        next
      end
      new_line = remove_words(old_line, words)

      new_xcconfig = xcconfig.sub(old_line, new_line)
      File.open(xcconfig_path, "w") { |file| file << new_xcconfig }
    end
  end
end
  # ---------- end of change ------------

end

target 'testProject-tvOS' do
  # Pods for testProject-tvOS

  target 'testProject-tvOSTests' do
    inherit! :search_paths
    # Pods for testing
  end
end

@rahamin1
Please try to change the
auto_process_target('testProject', 'SquareReaderSDK', installer)
to
auto_process_target(['testProject'], 'SquareReaderSDK', installer)

The main target should be an array.

@bestwnh Thanks! Missed that...
I see now that I am getting an error for something else:

undefined methodbuild_configurations' for nil:NilClass...`

Any idea what I am missing?

@rahamin1 It looks like the target name is incorrect. Maybe because your SquareReaderSDK is not import by CocoaPods? You can try to replace all two 'Pods-' to ''. It make the script no longer auto change the SquareReaderSDK to Pods-SquareReaderSDK.

You can also check the .xcconfig file to confirm the target name. The information is in my blog post link of the answer in stackoverflow.

@bestwnh can you send me an email? I would like to ask you something in an email...
_yossi.[email protected]_

Regarding the name of the pod (SquareReaderSDK), there is no such pod...
The installation process for this package (https://bit.ly/3d4SPA3) doesn't use cocoapods...

This is the error I am getting:

objc[7955]: Class PodsDummy_CocoaAsyncSocket is implemented in both /Users/user172615/Library/Developer/CoreSimulator/Devices/B4BCD2F3-8787-4F77-AA76-5DB45FA2EA7C/data/Containers/Bundle/Application/36574EF1-2F18-444B-B47B-F9FEA43DC7BE/plumpPlum.app/Frameworks/SquareReaderSDK.framework/SquareReaderSDK (0x10ed07c90) and /Users/user172615/Library/Developer/CoreSimulator/Devices/B4BCD2F3-8787-4F77-AA76-5DB45FA2EA7C/data/Containers/Bundle/Application/36574EF1-2F18-444B-B47B-F9FEA43DC7BE/plumpPlum.app/plumpPlum (0x10ac05238). One of the two will be used. Which one is undefined.

And this are the contents of the Pods directory:

image

I have uploaded a sample repo that demonstrates the problem to https://github.com/rahamin1/duplicate

Was this page helpful?
0 / 5 - 0 ratings

Related issues

steffendsommer picture steffendsommer  路  3Comments

pallaviMN picture pallaviMN  路  3Comments

iosdev-republicofapps picture iosdev-republicofapps  路  3Comments

dawnnnnn picture dawnnnnn  路  3Comments

5SMNOONMS5 picture 5SMNOONMS5  路  3Comments