使用Cocoapods构建静态库时防止出现重复符号

Eri*_*ber 21 objective-c static-libraries ios cocoapods

虽然我已经看到很多关于Cocoapods和静态库的问题,但大多数人似乎都认为你最终会拥有一个带有静态库和最终目标应用程序的工作区.

在我的场景中,我正在构建一个静态库.更具体地说,我正在攻击MyLib.framework供用户使用.我真的很想管理MyLib.framework与Cocoapods的依赖关系,但是当我的库的消费者使用Cocoapods 时,它会产生很多痛点.

例如,我的库有一个AFNetworking依赖项,我用Cocoapods管理它.当我构建我的库时,它链接在libPods.a中,其中包括AFNetworking,以及一些"虚拟"文件/对象.如果我的框架的用户也使用Cocoapods来构建他们的应用程序,他们会看到如下内容:

duplicate symbol _OBJC_METACLASS_$_PodsDummy_Pods in:
    /Users/erikkerber/Dropbox/Projects/MillMain/MyLib.framework/BuddySDK(Pods-dummy.o)
    /Users/erikkerber/Library/Developer/Xcode/DerivedData/MillMain-fngfqhlslygksgcfuciznkpqfrbr/Build/Products/Debug-iphonesimulator/libPods.a(Pods-dummy.o)
duplicate symbol _OBJC_CLASS_$_PodsDummy_Pods in:
    /Users/erikkerber/Dropbox/Projects/MillMain/MyLib.framework/BuddySDK(Pods-dummy.o)
    /Users/erikkerber/Library/Developer/Xcode/DerivedData/MillMain-fngfqhlslygksgcfuciznkpqfrbr/Build/Products/Debug-iphonesimulator/libPods.a(Pods-dummy.o)
ld: 2 duplicate symbols for architecture i386
Run Code Online (Sandbox Code Playgroud)

我想如果他们要添加一个AFNetworking依赖项,他们也会得到与AFNetworking相关的重复符号.

我计划最终使用Cocoapods分发MyLib,但我也希望能够分发MyLib.framework本身.

有没有办法在我的库中使用Cocoapods同时使Cocoapods对任何潜在用户都安全?

all*_*loy 16

简而言之,分发预构建库的唯一好方法是包含任何依赖项,而是将其留给用户.即在您的示例中,您将指示您的用户如何将AFNetworking添加到他们的项目中.这些dummy文件基本相同.

话虽如此,你当然可以选择多种预建的变体:

  • 包括所有依赖项.
  • 仅包含您的lib的源,将依赖项留给用户.

我们一直在讨论创建一个插件来生成独立的静态库,这是为了你想要的目的,但是还没有开始,可能需要更长的时间.(直到有人/任何人有时间.)

作为一种解决方法,您可以使用Podfile的post_install钩子来完全删除虚拟文件.(这些仅适用于像Testflight这样的非源库.)例如以下内容:

post_install do |installer|
  installer.project.targets.each do |target|
    source_files = target.source_build_phase.files
    dummy = source_files.find do |file|
      # TODO Fix this to the actual filename
      # puts "File: #{file.file_ref.name}"
      file.file_ref.name == 'TheDummyFile.m'
    end
    puts "Deleting source file #{dummy.inspect} from target #{target.inspect}."
    source_files.delete(dummy)
  end
end
Run Code Online (Sandbox Code Playgroud)

这是未经测试的代码.

post_install钩产生了的CocoaPods安装对象,从中可以得到Pods.xcodeproj目标,为此,你可以找到的文档在这里.从那里,您可以向下钻取并对项目执行任何操作,在运行此挂钩后将其保存到磁盘.


eli*_*ley 10

我遇到过同样的问题.我使用以下podfile格式使用cocoapods管理我的库的依赖项:

platform :ios, '6.0'
pod 'AFNetworking'
Run Code Online (Sandbox Code Playgroud)

这导致我的.a文件中有一个Pods-dummy.o文件.如果我然后使用相同的podfile格式将此库包含在另一个项目中,则它们都会创建一个Pods-dummy.o符号并导致链接器错误.解决方案是使用不同的podfile格式,这将导致命名空间的Pods-dummy符号:

platform :ios, '6.0'
target "MyProject" do
    pod 'AFNetworking'
end
Run Code Online (Sandbox Code Playgroud)

这会产生Pods-MyProject-dummy.o文件,该文件不会导致重复的符号.

注意:如果您将项目切换为使用新的podfile格式,请确保从项目中取消链接libPods.a,因为它会作为断开链接而挂起,因为新的pods库名为Pods-MyProject


Jer*_*ith 5

如果它们相同,您可以使用以下方法合并它们:

libtool (libtool -o merged.a file1.a file2.a)
Run Code Online (Sandbox Code Playgroud)

如果这不能解决错误,则有以下选项:http: //atnan.com/blog/2012/01/12/avoiding-duplicate-symbol-errors-during-linking-by-removing-classes-from-静态库