Cocoapods: Duplicated implementation with pod 1.2.1

Created on 1 Aug 2017  路  11Comments  路  Source: CocoaPods/CocoaPods

Report

After updating from 1.1.1 to 1.2.1 I see duplicated implementation for all the frameworks I use inside my internal framework. Like:

objc[33965]: Class CLSURLSession is implemented in both /Users/lucabartoletti/Library/Developer/Xcode/DerivedData/SampleCocoapodsIssue-fmnrtlootruozbdjmxepcxupyell/Build/Products/Debug-iphonesimulator/SampleCocoapodsIssueFramework.framework/SampleCocoapodsIssueFramework (0x109f710e0) and /Users/lucabartoletti/Library/Developer/CoreSimulator/Devices/5CBE6348-71A0-4B47-8DD7-FF23E4E22705/data/Containers/Bundle/Application/DB2EA3E2-0D43-454F-AED3-8896779C621F/SampleCocoapodsIssue.app/SampleCocoapodsIssue (0x106aa0f38). One of the two will be used. Which one is undefined.

This started happening after 1.2.1 update.

So I created a sample projects that has the same structure of my real Podfile.

project 'SampleCocoapodsIssue.xcodeproj'

platform :ios, '9.0'

abstract_target 'Phone' do
  target 'SampleCocoapodsIssueFramework' do
    pod 'Fabric'
    pod 'Crashlytics'
  end

  abstract_target 'App'  do
    target 'SampleCocoapodsIssue' do
      pod 'AFNetworking'    
    end
  end
end

What did you do?

Updated to 1.2.1
Run pod install

What did you expect to happen?

To not see duplicated symbols. When I run pod install with 1.1.1 my xcconfig are:

Pods-Phone-App-SampleCocoapodsIssue.debug

ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/AFNetworking" "${PODS_ROOT}/Headers/Public/Crashlytics" "${PODS_ROOT}/Headers/Public/Fabric"
LIBRARY_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/AFNetworking"
OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/AFNetworking" -isystem "${PODS_ROOT}/Headers/Public/Crashlytics" -isystem "${PODS_ROOT}/Headers/Public/Fabric"
OTHER_LDFLAGS = $(inherited) -ObjC -l"AFNetworking" -framework "CoreGraphics" -framework "MobileCoreServices" -framework "Security" -framework "SystemConfiguration"
PODS_BUILD_DIR = $BUILD_DIR
PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}/Pods

Pods-Phone-SampleCocoapodsIssueFramework.debug

ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Crashlytics/iOS" "${PODS_ROOT}/Fabric/iOS"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/AFNetworking" "${PODS_ROOT}/Headers/Public/Crashlytics" "${PODS_ROOT}/Headers/Public/Fabric"
OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/AFNetworking" -isystem "${PODS_ROOT}/Headers/Public/Crashlytics" -isystem "${PODS_ROOT}/Headers/Public/Fabric"
OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"z" -framework "Crashlytics" -framework "Fabric" -framework "Security" -framework "SystemConfiguration" -framework "UIKit"
PODS_BUILD_DIR = $BUILD_DIR
PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}/Pods

What happened instead?

After pod install with 1.2.1 I see:

Pods-Phone-App-SampleCocoapodsIssue.debug

FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Crashlytics/iOS" "${PODS_ROOT}/Fabric/iOS"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/AFNetworking" "${PODS_ROOT}/Headers/Public/Crashlytics" "${PODS_ROOT}/Headers/Public/Fabric"
LIBRARY_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/AFNetworking"
OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/AFNetworking" -isystem "${PODS_ROOT}/Headers/Public/Crashlytics" -isystem "${PODS_ROOT}/Headers/Public/Fabric"
OTHER_LDFLAGS = $(inherited) -ObjC -l"AFNetworking" -l"c++" -l"z" -framework "CoreGraphics" -framework "Crashlytics" -framework "Fabric" -framework "MobileCoreServices" -framework "Security" -framework "SystemConfiguration" -framework "UIKit"
PODS_BUILD_DIR = $BUILD_DIR
PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
PODS_ROOT = ${SRCROOT}/Pods

Pods-Phone-SampleCocoapodsIssueFramework.debug

FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Crashlytics/iOS" "${PODS_ROOT}/Fabric/iOS"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/AFNetworking" "${PODS_ROOT}/Headers/Public/Crashlytics" "${PODS_ROOT}/Headers/Public/Fabric"
OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/AFNetworking" -isystem "${PODS_ROOT}/Headers/Public/Crashlytics" -isystem "${PODS_ROOT}/Headers/Public/Fabric"
OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"z" -framework "Crashlytics" -framework "Fabric" -framework "Security" -framework "SystemConfiguration" -framework "UIKit"
PODS_BUILD_DIR = $BUILD_DIR
PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
PODS_ROOT = ${SRCROOT}/Pods

the problem is that the App OTHER_LDFLAGS contains Fabric and Crashlytics. If I run the same pod file with 1.1.1 this doesn't happen.

CocoaPods Environment

### Stack

CocoaPods : 1.2.1
Ruby : ruby 2.4.0p0 (2016-12-24 revision 57164) [x86_64-darwin16]
RubyGems : 2.6.11
Host : Mac OS X 10.12.5 (16F73)
Xcode : 8.3.3 (8E3004b)
Git : git version 2.11.0 (Apple Git-81)
Ruby lib dir : /Users/lucabartoletti/.rvm/rubies/ruby-2.4.0/lib
Repositories : master - https://github.com/CocoaPods/Specs.git @ 64e7a481da1576c895c65a4ae4e2de181be6faf7

### Installation Source

Executable Path: /Users/lucabartoletti/.rvm/gems/ruby-2.4.0/bin/pod

### Plugins

cocoapods-amimono : 0.0.10
cocoapods-deintegrate : 1.0.1
cocoapods-plugins : 1.0.0
cocoapods-search : 1.0.0
cocoapods-stats : 1.0.0
cocoapods-trunk : 1.2.0
cocoapods-try : 1.1.0

### Podfile

```ruby
project 'SampleCocoapodsIssue.xcodeproj'

# Uncomment the next line to define a global platform for your project
platform :ios, '9.0'




abstract_target 'Phone' do
  target 'SampleCocoapodsIssueFramework' do
    pod 'Fabric'
    pod 'Crashlytics'
  end

  abstract_target 'App'  do
    target 'SampleCocoapodsIssue' do
      # Uncomment the next line if you're using Swift or would like to use dynamic frameworks
      # use_frameworks!

      pod 'AFNetworking'    
    end
  end
end

Project that demonstrates the issue

Sample project:
https://www.dropbox.com/s/accpjnjhb31ktwx/SampleCocoapodsIssue.zip?dl=0

moderate confirmed

Most helpful comment

Also getting the same issue, with Cocoapods versions 1.2.1 and 1.3.0.beta.2.
In our case, we have specific pods causing us issues - Firebase, Fabric and AppsFlyerFramework - other pods are fine.

The issue is easily reproducible by:

  1. creating a project
  2. adding an embedded Cocoa Touch framework
  3. add any of these dependencies to the framework

Result: Errors in output and at least with Firebase, results in a crash after a few seconds.

Here's the Podfile from a quick reproduction.

All 11 comments

Also getting the same issue, with Cocoapods versions 1.2.1 and 1.3.0.beta.2.
In our case, we have specific pods causing us issues - Firebase, Fabric and AppsFlyerFramework - other pods are fine.

The issue is easily reproducible by:

  1. creating a project
  2. adding an embedded Cocoa Touch framework
  3. add any of these dependencies to the framework

Result: Errors in output and at least with Firebase, results in a crash after a few seconds.

Here's the Podfile from a quick reproduction.

The problem probably arises because the pods specified in the framework are also linked to your app that hosts the frameworks.

You may be able to remove the double linking via a post_install hook in the meantime.

This might require bigger changes to the codebase to re-wire correctly the dependencies.

PRs welcome!

Is it possible to setup a post_install hook to remove all dependencies from a whole framework?

I can find examples like the following - where you can remove specific source files - but hopefully you could just specify the specific pods/frameworks you want to completely ignore?

post_install do |installer|
    installer.pods_project.targets.each do |target|
        if target.name == 'Pods-Earthlings'
            source_files = target.source_build_phase.files
            dummy = source_files.find do |file|
                file.file_ref.name == 'SomeDuplicate.m'
            end
            source_files.delete dummy
        end
    end
end

Hi, thanks @dnkoutso. Not sure if you are replying to me or to @yahmad.

In my case, as reproduced in the sample project above, with the same project and same Podfile I have the Class XXX is implemented in both problem with Cocoapods 1.2.1 but not if you use 1.1.1.

So my question is why 1.2.1 started linking those framework in the App while 1.1.1 is not doing so? It's an expected thing or is a bug

To say it in other words, It is still unclear to me if 1.2.1 is buggy and 1.1.1 is right or if 1.2.1 is doing the right thing and it exposed a problem in our project config

This issue is occurring for me in 1.3.1.
Like @yahmad, the steps to reproduce are extremely simple. I have created a project with an app target and a Cocoa framework target, which is linked against my app target. In my Podfile, I have declared 'Fabric' a dependency of my framework target, which conspicuously uses a vendored framework. Here is my Podfile:

platform :ios, '10.0'
use_frameworks!

target 'MyKit' do
    pod 'Fabric'
end

target 'DuplicateSymbols' do
end

(MyKit is my framework target, and DuplicateSymbols is my app target)

This is generally confirmed. As I've explained its because the pods on a dynamic framework target are ALSO linked to the app target.

If I find time I will attempt a fix but in the meantime as I said in the previous response PRs welcome.

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 should stay open

Posting the workaround that I'm currently using in case it's helpful to anyone. It was previously mentioned that you can use a post_install hook to remove the double linking, but I find it cleaner to do it in a pre_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/6918#issuecomment-325686872, add the following to your Podfile.

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

From what I can tell, this issue was first introduced in https://github.com/CocoaPods/CocoaPods/pull/6575 and first released as v1.2.1.

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

Related issues:

I hoped that #7592 would also fix this, but in my tests it doesn't

I make a workaround to fix this issue. https://stackoverflow.com/a/52773670/2446684

Was this page helpful?
0 / 5 - 0 ratings