静态地将私有库链接到公共库以隐藏符号

Statically link a private library into a public one to hide symbols

本文关键字:符号 隐藏 链接 静态      更新时间:2023-10-16

考虑以下内容:

  • 我正在C++中开发一个静态库X,它在内部使用著名的静态库Y v2.0
  • 我只想分发一个库X',即X和Y静态链接/合并以供内部使用
  • 开发人员希望在其可执行文件中使用X'
  • 此外,他需要Y v1.0(而不是像我一样的v2.0)
  • Y v1.0和v2.0有一些共同的符号,并且这些共同的符号中的一些行为也不同

我开发了X,并严格要求它的一些内部业务使用Y v2.0。也就是说,我无论如何都无法恢复到Y v1.0。
另一方面,开发人员对使用Y v1.0也有类似的限制。

正如您已经讨论过的,问题是:如何在不导出Y符号的情况下将Y链接到X内部以避免冲突?Y已经建立好了,我可能不想修改它的源代码或构建设置(如果公开的话)。

为了把更多的东西放在地球上,我正在设计一个SDK,它肯定需要一些第三方库,比如zlib。在我的开发过程中,我将依赖zlib v1.2.2.3.4.5.rc6,因为我广泛而成功地使用和测试了它,并且如果我更改版本,我无法承担所需的SDK测试/修复
SDK将提供的所有静态或常规链接库都必须隐藏第三方静态库

潜在客户可能会受到类似的限制(他需要zlib v7.8.9),那么我如何避免符号冲突?再次,可能不改变原始源代码(名称空间等)。

更复杂的是,SDK是多平台的,这意味着我需要不同的方法来解决问题,这取决于使用的平台(Windows、Linux、Mac OS、iOS、Android…)和编译器(例如,MSVC++和g++)

谢谢。

更新
我似乎是这个问题的供应商2:链接一个库的多个版本
bstpierre的答案似乎是一个可行的解决方案,但我不确定它是否有效,也不确定它能否在*nix以外的操作系统上复制。

我在静态库中遇到过很多次这个问题,最近一次是在MSVCRT中。正如一位评论者所指出的,只有一个可执行文件,"一个定义规则"就会成为障碍。除了修补二进制文件之外,我真的没有办法解决这个问题。您必须"深入"地执行此操作——捕获静态库Y(zlib)对其自身外部链接对象的所有内部引用。

在这种情况下,我建议使用动态库(DLL或SO)。这将增加部署的复杂性。但它提供了一个可执行的"防火墙",允许具有相同名称的全局对象驻留在每个二进制文件中而不会发生冲突。即便如此,如果应用程序和DLL都有冲突的第三方依赖关系,它也会带来问题。不过,这可能是最好的选择。