滥用soversion次要修订以支持可选的依赖项

时间:2014-06-29 17:04:45

标签: c++ plugins shared-libraries versioning dependency-management

我正在编写一个包含许多可选依赖项的C ++包。能够在没有任何这些依赖项的情况下使用该包非常重要,然后能够在不重新编译软件的情况下添加依赖项。如果依赖项不可用,我想回到某些默认行为。

每个可选的依赖项对应于包的不同共享库,我正在考虑(ab)使用“soversions”来实现此功能,并使次要修订版0对应于回退实现。

为了说明,假设有一个核心模块编译成一个名为“libmy_core.so”的共享库。我有一个可选功能(取决于“libmy_core.so”以及一些外部包)编译到共享库“libmy_feature.so.1.1”。但是为了确保代码在没有这个库的情况下工作,我还构建了一个名为“libmy_feature.so.1.0”的回退模块,其中依赖于“libmy_core.so”。

然后我将分发“libmy_core.so”和“libmy_feature.so.1.0”。如果用户稍后添加了可选的依赖项,则还将安装“libmy_feature.so.1.1”(并优先于“libmy_feature.so.1.0”)。

这是一个可行的解决方案还是有更好的解决方案?类似的方法是否也适用于非Linux系统,特别是OS X和Windows?

2 个答案:

答案 0 :(得分:3)

  

这是一个可行的解决方案还是有更好的解决方案?

这不是一个好的解决方案。你正在为自己和你的用户设置依赖地狱。以下是可行的替代方案。它与plugin库的概念有关。

您可以在公开C接口的共享库中构建可选功能。然后,您的应用程序/库可以使用dlopen检查共享库的优先级,然后使用dlsym获取接口。如果找不到共享库或者没有公开所需的接口,那么您的应用程序/库可以使用回退行为,该行为在应用程序/库本身中实现。您必须小心您的应用程序/库不依赖于可选库,而只使用dlsym返回的函数指针。

使用C接口的原因是它提供了稳定的二进制接口。使用C ++类型时,在混合使用不同编译器编译的共享库或使用不同的编译器设置时,可能会得到未定义的行为。

在Windows上,您可以使用LoadLibraryGetProcAddress执行相同操作。

答案 1 :(得分:0)

我会使用dlopen加载可选库。然后你只需要一个库,并且可以使用dlopen返回值在运行时检测另一个库。