【问题标题】:Prevent duplicate symbols when building static library with Cocoapods使用 Cocoapods 构建静态库时防止重复符号
【发布时间】:2014-02-10 12:35:00
【问题描述】:

虽然我看到很多关于 Cocoapods 和静态库的问题,但其中大多数似乎都假设您最终将拥有一个包含静态库和最终目标应用程序的工作区。

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

例如,我的库有一个 AFNetworking 依赖项,我使用 Cocoapods 管理它。当我构建我的库时,它会链接到包含 AFNetworking 的 libPods.a 以及一些“虚拟”文件/对象。如果我的框架的用户也使用 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

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

我计划最终也将 MyLib 与 Cocoapods 一起分发,但我也希望能够分发 MyLib.framework 本身。

有什么方法可以在我的库中使用 Cocoapods,同时确保 Cocoapods 对任何潜在用户都是安全的?

【问题讨论】:

  • 您打算分发框架的源代码,还是只分发二进制文件?
  • @StefanFisk 它将是开源的,但对于简单的情况,我希望允许用户简单地下载 MyLib.framework,并且只有在他们想要自定义它时才进入源代码。

标签: ios objective-c static-libraries cocoapods


【解决方案1】:

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

话虽如此,您当然可以选择多个预建变体:

  • 包括所有依赖项。
  • 仅包含您的库的源代码,将依赖项留给用户。

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

作为一种解决方法,您可以使用 Podfile 的 post_install hook 来完全删除虚拟文件。 (这些只需要像 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

这是未经测试的代码。

post_install 钩子生成 CocoaPods 安装程序对象,您可以从中获取 Pods.xcodeproj 目标,您可以找到文档here。从那里你可以向下钻取并对项目做任何你喜欢的事情,在运行这个钩子后保存到磁盘。

【讨论】:

  • 非常感谢,您证实了我的怀疑。我会考虑你的方法,尽管我可能会采用“只是为所有依赖对象的名称添加前缀”方法而不使用 Cocoapods。
  • 是的,这确实是另一条路线。您可能想考虑使用rentzsch.tumblr.com/post/40806448108/… 之类的东西,以便您的代码可以轻松地在 CocoaPods 环境中使用> 重新命名的依赖关系。
【解决方案2】:

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

platform :ios, '6.0'
pod 'AFNetworking'

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

platform :ios, '6.0'
target "MyProject" do
    pod 'AFNetworking'
end

这会生成一个 Pods-MyProject-dummy.o 文件,不会导致重复符号。

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

【讨论】:

  • h/t 了解有关取消链接 libPods.a 的信息!知道每次运行 pod install 时如何保持 libPods.a 链接吗?
  • 默认情况下,静态库依赖项不会链接到静态库产品中,因此虽然@alloy 关于不包括依赖项的建议是合理的,但我认为他或她的大部分回答都忽略了这个问题。删除虚拟对象文件确实有效,而且不是一个坏主意,但我认为我认为这个解决方案更干净。
【解决方案3】:

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

libtool (libtool -o merged.a file1.a file2.a)

如果这不能解决错误,有这个选项: http://atnan.com/blog/2012/01/12/avoiding-duplicate-symbol-errors-during-linking-by-removing-classes-from-static-libraries

【讨论】:

    【解决方案4】:

    参考http://guides.cocoapods.org/syntax/podfile.html#post_install & http://pdx.esri.com/blog/2013/12/13/namespacing-dependencies/

    我使用“手动重命名所有符号”方法。我遇到了重复的符号_OBJC_METACLASS_$_PodsDummy_Pods,所以我在Podfile中添加并编辑了post_install,以避免重复符号

    post_install do |installer_representation|
        installer_representation.pods_project.targets.each do |target|
            target.build_configurations.each do |config|
                config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = '$(inherited), PodsDummy_Pods=SomeOtherNamePodsDummy_Pods'
            end
        end
    end
    

    【讨论】:

    • 只需将project 替换为pods_project。这是由于最近对 Cocoapods 的更新。
    【解决方案5】:

    当我手动将一些外部代码添加到我的项目 AFNetworking 中时,我遇到了这个问题,例如,然后添加了一些也包含它的 pod。

    只需从我自己的项目(而不是 pod)中删除 AFNetworking 即可解决问题。

    【讨论】:

      【解决方案6】:

      将每个冲突符号的条目添加到您的其他 C 标志,例如“-DAFHTTPClient=AF2HTTPClient” Xcode Multiple Static Libraries and Duplicate Symbols

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-06-10
        • 2014-03-04
        • 2019-11-16
        • 2018-11-06
        • 1970-01-01
        • 2018-01-13
        • 2014-12-07
        • 2016-01-22
        相关资源
        最近更新 更多