https://kotlinlang.org logo
#ios
Title
# ios
w

Will Hess

11/09/2021, 7:15 PM
I am running into an issue regarding duplicate frameworks with cocoapods. I am trying to consume a kotlin generated framework into 3 modules inside of my xcode projects: • iosSdk • iosSdkUx • iosSdkSampleApplication I have tried adding this flag to the kotlin project, but am still running into the error.
Copy code
kotlin.native.cacheKind=none
I also have a post install script inside of my podfile which was working when I was only consuming the kotlin generated framework in
iosSdk
and
iosSdkUx
. But when trying to add the third it fails (
iosSdkSampleApplication
). (SEE THREAD FOR PODFILE) Here is the error I am getting:
Copy code
objc[29904]: Class ISSDouble is implemented in both /Users/ME/Library/Developer/Xcode/DerivedData/iosSdk-ftsmsdlkscvzlmdbohckpjheeupx/Build/Products/Debug-iphonesimulator/iosSdkUx.framework/iosSdkUx (0x110508d60) and /Users/ME/Library/Developer/CoreSimulator/Devices/7C739BFB-DFD9-4F88-A2D4-4185065B258D/data/Containers/Bundle/Application/C98D5D0A-45C5-43F5-A4AA-70C42E3E283F/iosSdkSampleApplication.app/iosSdkSampleApplication (0x103bbb2f0). One of the two will be used. Which one is undefined.
Copy code
PROJECT_ROOT_DIR = File.dirname(File.expand_path(__FILE__))
PODS_DIR = File.join(PROJECT_ROOT_DIR, 'Pods')
PODS_TARGET_SUPPORT_FILES_DIR = File.join(PODS_DIR, 'Target Support Files')

post_install do |installer|

  remove_static_framework_duplicate_linkage({
     'iosSdk' => ['SharedSdk'],
     'iosSdkUx' => ['SharedSdk'],
     'iosSdkSampleApplication' => ['SharedSdk']
  })

  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      #config.build_settings['LD_NO_PIE'] = 'NO'
      if Gem::Version.new('9.0') > Gem::Version.new(config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'])
        config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '9.0'
      end
    end
  end
end

# CocoaPods provides the abstract_target mechanism for sharing dependencies between distinct targets.
# However, due to the complexity of our project and use of shared frameworks, we cannot simply bundle everything under
# a single abstract_target. Using a pod in a shared framework target and an app target will cause CocoaPods to generate
# a build configuration that links the pod's frameworks with both targets. This is not an issue with dynamic frameworks,
# as the linker is smart enough to avoid duplicate linkage at runtime. Yet for static frameworks the linkage happens at
# build time, thus when the shared framework target and app target are combined to form an executable, the static
# framework will reside within multiple distinct address spaces. The end result is duplicated symbols, and global
# variables that are confined to each target's address space, i.e not truly global within the app's address space.
#
# Previously we avoided this by linking the static framework with a single target using an abstract_target, and then
# provided a shim to expose their interfaces to other targets. The new approach implemented here removes the need for
# shim by modifying the build configuration generated by CocoaPods to restrict linkage to a single target.
def remove_static_framework_duplicate_linkage(static_framework_pods)
  puts "Removing duplicate linkage of static frameworks"

  Dir.glob(File.join(PODS_TARGET_SUPPORT_FILES_DIR, "Pods-*")).each do |path|
    pod_target = path.split('-', -1).last

    static_framework_pods.each do |target, pods|
      next if pod_target == target
      frameworks = pods.map { |pod| identify_frameworks(pod) }.flatten

      Dir.glob(File.join(path, "*.xcconfig")).each do |xcconfig|
        lines = File.readlines(xcconfig)

        if other_ldflags_index = lines.find_index { |l| l.start_with?('OTHER_LDFLAGS') }
          other_ldflags = lines[other_ldflags_index]

          frameworks.each do |framework|
            other_ldflags.gsub!("-framework \"#{framework}\"", '')
          end

          File.open(xcconfig, 'w') do |fd|
            fd.write(lines.join)
          end
        end
      end
    end
  end
end

def identify_frameworks(pod)
  frameworks = Dir.glob(File.join(PODS_DIR, pod, "**/*.framework")).map { |path| File.basename(path) }

  if frameworks.any?
    return frameworks.map { |f| f.split('.framework').first }
  end

  return pod
end
I fixed this but removing all the custom scripts from my podfile and setting the framework to dynamic in the kotlin project.
Then embedding the framework in my sample application
18 Views