我正在编写一个包含许多可选依赖项的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?
答案 0 :(得分:3)
这是一个可行的解决方案还是有更好的解决方案?
这不是一个好的解决方案。你正在为自己和你的用户设置依赖地狱。以下是可行的替代方案。它与plugin库的概念有关。
您可以在公开C接口的共享库中构建可选功能。然后,您的应用程序/库可以使用dlopen检查共享库的优先级,然后使用dlsym获取接口。如果找不到共享库或者没有公开所需的接口,那么您的应用程序/库可以使用回退行为,该行为在应用程序/库本身中实现。您必须小心您的应用程序/库不依赖于可选库,而只使用dlsym
返回的函数指针。
使用C接口的原因是它提供了稳定的二进制接口。使用C ++类型时,在混合使用不同编译器编译的共享库或使用不同的编译器设置时,可能会得到未定义的行为。
在Windows上,您可以使用LoadLibrary和GetProcAddress执行相同操作。
答案 1 :(得分:0)
我会使用dlopen加载可选库。然后你只需要一个库,并且可以使用dlopen返回值在运行时检测另一个库。