使用Cocoapods构建静态库

17
我正在尝试构建一个静态库,其中在Podfile文件中指定了不同的依赖项(例如AFNetworking)。我不希望这些依赖项被包含在最终的静态库(libMyProject.a)中,我只想链接它们,并创建一个名为MyProject.Podspec的文件,在其中放置相同的依赖项。
问题在于当我构建libMyProject.a时,libPods.a被链接并包含在其中,因此,如果我分发libMyProject.a并且其他人将其集成到使用某些相同依赖项的项目中,就会出现重复符号的问题。
如何在链接libPods.a库的同时不将其包含在libMyProject.a中?它应该像链接其他现有框架一样工作。
谢谢!

如果您下面添加的答案是正确的,请将其标记为正确,以便此问题不再显示为打开状态。 - memmons
3个回答

12

我通过从Build Phases部分的“链接二进制文件”中删除libPods.a库来解决了它。


我相信这是正确的答案,并且我在这里详细阐述了我的解决方案:https://dev59.com/kmQn5IYBdhLWcg3w7a2K#17869668 - Daniel Wood
4
有没有一种聪明的方式来自动化这个移除过程?我已经尝试了多种方法,但都没有成功。 - Wilmar
@Wilmar,请看我的回答,了解自动删除(或更具体地说,如何避免首次添加)。 - Craig Russell

6
虽然从“链接二进制文件库”构建阶段手动删除libPods.a确实有效,但真正的答案是不要让它在第一次添加时就被添加到那里。
之所以会添加它,是因为pod install命令正在查找静态库目标作为其要链接的目标之一。这可能是因为它是列表中的第一个目标(如果您没有明确指定目标,则cocoapods的实现会导致它选择第一个目标),也可能是因为您已在“link_with”部分中明确说明了它。
我发现的答案是使用Podfile的link_with部分明确说明您的目标,并省略静态库目标。 pods项目仍将创建,并像您预期的那样引入您的依赖项,但是libPods.a不会添加到您的静态库的构建阶段中。
唯一的问题是要将什么放入link_with部分,如果不是您的静态库。如果您有其他目标要链接(例如iPhone应用程序目标),那是个好选择。但是,如果您的唯一真正目标是您的静态库,那么您需要一个小技巧。
到目前为止,我的成功策略是创建一个静态库目标(是的,与您的主静态库分开)并将其称为“Dummy”。在您的Podfile的link_with部分中指定此目标。
这有点不舒服,但确实有效。
platform :ios, '5.1.1'

link_with ['Dummy']

pod 'AFNetworking', '= 1.3.1'

1
这个方法很有效,但你可能还需要将静态库目标的配置设置为 Pods.xcconfig,否则依赖库的头文件无法在你的静态库中使用。 - murat
您可能需要手动将Cocoapods生成的xcconfig(例如Pods.debug.xcconfig)添加到Xcode项目的配置中(Project> Info> Configurations),以使头文件搜索正常工作。我确实让这个模式起作用了,但我想出了另一种解决方案(https://dev59.com/DmQn5IYBdhLWcg3wGUAX#30057642)。 - big_m

1
参考库默认情况下不包含在静态库产品中。您看到的链接器冲突更可能是由于您的静态库和客户端应用程序都使用默认(隐式)Pod目标的结果。
每个Cocoapods生成的目标都包括一个编译到产品中的“Pods-target-dummy.m”文件;如果您使用默认的Pods目标,它只被称为“Pods-dummy.m”。当库和客户端都使用默认目标时,从编译虚拟文件产生的相同符号将导致链接错误。
我尝试了Craig's answer的变体,并发现link_with语句也负责连接Cocoapods生成的xcconfig,该xcconfig提供控制头文件搜索路径的编译器标志。您当然可以手动添加xcconfig(或头文件搜索路径项目设置),但我正在寻找一个可重复使用的解决方案,以供我的团队使用。
我的解决方案是为库创建一个明确的目标,名称不太可能与客户端项目冲突(例如,库的名称):
target 'XYZLibrary' do
    pod 'AFNetworking', '2.5.2'
    ...
end

如果您的静态库目标(在Xcode项目中)的名称不同,可以在target块中包含link_with语句,但是如果只有一个目标,则我通常更喜欢在两个位置使用相同的名称,使link_with无需。
如果您有一个单元测试目标,请创建两个单独的目标。(我目前def了一组常用的pods,这些pods在两个目标中都使用,因为抽象目标当前不是一个选项,但它们可能有一天成为一个选项。)它看起来像这样:
def common_pods
  pod 'AFNetworking', '2.5.2'
end

target 'XYZLibrary' do
  common_pods
end

target 'XYZLibraryTests' do
  common_pods
end

关键在于不要在Podfile的根目录中有任何pod元素,这样Cocoapods就不会生成默认目标。这样,每个产品都会得到一个独特的“Pods-target-dummy.m”,当这些对象文件链接在一起时就不会发生冲突。

哈哈,刚发现 eliasbagley 已经发布了相同的解决方案! - big_m

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接