Art*_*yom 24 c++ unix compatibility boost abi
我正在研究某个C++库(或更多框架).我想让它向后兼容以前的版本,不仅保留了API兼容性,还保留了ABI(就像Qt那样出色的工作).
我使用Boost的许多功能,对我来说,这使得向后兼容性变得不可能,除非我强迫用户拥有完全相同(有时是旧版本)的Boost.
有没有办法(没有重写1/2 Boost)在其命名空间周围做一些"前缀"/重命名它以防止它干扰用户版本的Boost?
例如,我的libXYZ使用Boost 1.33并且它有类boost::foo.在版本1.35 boost::foo升级并添加了新成员,因此,boost::foo从1.33和1.35不兼容ABI.因此,libXYZ的用户必须使用Boost 1.33或使用Boost 1.35重新编译libXYZ(可能已经以XYZ无法编译的方式破坏了某些API).
注意:我说的是带有ELF的UNIX/Linux操作系统,其中动态链接类似于静态链接,因此您无法链接两个不同版本的库,因为符号会产生干扰.
我可能想到的一个合适的解决方案是将Boost放在其他一些私有命名空间中.因此,libXYZ将使用::XYZ::boost::foo而不是::boost::foo.这可以防止与用户可能使用的其他版本的Boost冲突.
因此,libXYZ将继续使用Boost 1.33与其他命名空间静态或动态链接,假设它:
有没有办法用Boost做这些事情?
编辑:最后我决定创建一个脚本,将源中的所有boost符号重命名为某个自定义符号.
基本原理:构建过程的简化,独立于编译器可见性支持,它的可见性仅适用于动态库,对于静态,这不起作用,因此我需要为每种类型的库提供单独的构建和依赖.
该脚本可在那里找到:http://art-blog.no-ip.info/files/rename.py
编辑2:最新版本的Boost BCP支持命名空间重命名.
Zif*_*fre 29
基本上,只需确保库的公共接口不会暴露Boost.您可以随时在内部使用它.通常,让库的接口依赖于另一个库是不好的(除非它依赖于像STL这样的标准库).Boost几乎适合"标准"库类别,但其ABI变化太大,以至于您的界面不应该使用它.
为确保不暴露Boost符号,您可以执行以下操作:
A.编译-fvisibility=hidden并标记所有公共符号__attribute__((visibility("default"))).您可以使用宏来简化:
#define ABI __attribute__((visibility("default")))
Run Code Online (Sandbox Code Playgroud)
B.做这样的事情:
#pragma GCC visibility push(hidden)
#include <boost/whatever.hpp>
#pragma GCC visibility pop
Run Code Online (Sandbox Code Playgroud)
您还应该将其包装在您不希望导出的所有其他内部符号周围,或者使用声明__attribute__((visibility("hidden"))).同样,您可以使用宏来使这更容易:
#define INTERNAL __attribute__((visibility("hidden")))
Run Code Online (Sandbox Code Playgroud)
在这些选项中,我更喜欢A,因为它会让您明确考虑导出哪些符号,因此您不会意外导出您不想要的内容.
顺便说一句,您可以在Ulrich Drepper的" 如何编写共享库"中找到有关制作DSO的更多信息.
通常,除了标准C绑定之外,您不能依赖C++中的任何类型的ABI.但根据您做出的假设,您可以在界面中使用越来越多的C++.
我发现这在步骤伟大的文章,让您的API的转成稳定的ABI.例如,永远不要在您的接口上传递标准C++库(或Boost)数据类型; 它可以通过修复库的小错误来实现收支平衡.
发布ABI兼容API时需要注意的一些问题示例如下:
.h文件中发布的内容以及分配发生的位置.如果您关注链接的文章,您将找到解决这些问题和其他问题的方法.
编辑:
我还发现了一篇由Microsoft发布的有趣文章,它描述了COM接口如何工作,通过采用C++项目并将其转换为COM.我认为微软开发COM的主要原因之一是解决C++所具有的脆弱二进制接口问题,因此他们可以使用面向发布对象的API发布DLL.