链接共享另一个静态库的静态库

16
我目前有一个非常大的代码库,使用单个 Xcode 项目管理,我称之为项目 X,现在我正在将它划分为若干子项目(项目 A,B,C等)。
到目前为止,这些项目都可以独立编译并生成静态库。 项目 B项目 C 需要使用由 项目 A 生成的静态库来进行编译。
我有另一个 Xcode 项目,项目 Z,需要使用由 项目 B项目 C 生成的静态库。这里出现了问题。当 项目 Z 进入链接器阶段时,会出现问题-在 项目 B项目 C 的库中找到了与它们最初连接到的 项目 A 中重复的符号!
我对静态库的世界还比较陌生,不确定如何解决 项目 Z 的问题,或者如何修改其他项目,以便它们连接到相同的 项目 A 库。我有一种感觉这是不可能的。我有哪些选择?
编辑:
我应该澄清,项目 B项目 C 需要构建成单独的静态库,因为部分客户只需要其中一个。
此外,我在 OSX 和 iOS 平台上都遇到了这个问题。
我意识到我可以通过构建动态库来解决这个问题。但是,我不想这样做,而且在 iOS 上仍然存在同样的问题。
2个回答

20

静态库不应包含其他静态库(或第三方代码)。 静态库只是一组粘在一起的.o文件。 如果您有多个相同信息的副本,则会膨胀。

每个静态库应该只包含自己的代码。最终应用程序负责将所有需要的库链接在一起(包括库所需的库)。 这样,每个链接的东西都只有一份拷贝。


1
是的,你说得对,关于这个问题。我通过简单地不将项目B和项目C链接到项目A来解决了这个问题。项目B和C仍然将项目A作为依赖项引用,因此它们能够正常构建。由于客户端始终会将项目A与这些项目一起包含,因此所有符号都能被找到,事情就能正常运行。 - Jeff
1
@Jeff,你是如何将A作为“依赖项”使得其他构建项目可以进行,而不实际链接(包含)A在它们的构建中的呢? - johnbakers
1
@Rob 我注意到在 Xcode 中,如果我构建一个只包含另一个库的头文件而不链接到其他库二进制文件的静态库,则构建可以顺利完成。如果我使用实际的程序项目(而不是库)来执行此操作,则在链接阶段会出现未定义的定义(错误)。我认为,在构建库时,“跳过”链接阶段的这一部分是正常的,而实际的程序在构建时会进行额外的链接检查,对吗?(如果编译器被指示构建库,那么它实际上是否正在执行这项工作?) - johnbakers
1
@johnbakers 静态库只是一组未链接的.o文件,所以这是可以预期的。.h文件只是承诺在链接时会有符号可用。它们通常不会生成任何代码或分配(如果它们在C或ObjC中这样做通常是错误的;C++则不同)。构建静态库并不会“跳过链接阶段的这一部分”。当您构建静态库时,没有链接阶段。您将编译为.o,然后将它们粘合在一起(归档)到.a - Rob Napier
1
@focs 正确。您必须在文档中告诉他们。这不是一个可修复的问题。没有依赖管理器(CocoaPods、Carthage、SPM),就没有简单的解决方案来管理依赖关系。话虽如此,在 C/ObjC 中,您并不需要完美的版本匹配。类似的版本仍然可以成功链接。(显然,如果您依赖于特定版本的行为,那么可能会引入问题;即使使用框架也无法解决这个问题。) - Rob Napier
显示剩余5条评论

2
这似乎正是 CocoaPods 创建的解决方案。如果您为每个项目定义了 pods,则 Z 可以确定并链接到整个依赖链,而不会引入重复符号。

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