避免名称冲突的静态库建议

Suggestions for static library to avoid name collision

我们有两个库 - lib1 和 lib2。这两个库都使用第三个库,比如 lib3。如果我们的客户在使用静态链接的同一应用程序中使用 lib1 和 lib2,由于 lib3 中的函数在 lib1 和 lib2 中很常见,客户将面临符号冲突导致的链接问题。

我们可以访问 lib1、lib2、lib3 源代码。我们应该做哪些更改来避免命名冲突?

看了一些帖子后,C++ 中的命名空间似乎可以解决问题?但它在我们的例子中是否有效,因为 lib3 仍将被加载两次?

我会留下一个答案,因为这不适合评论。

据我了解,您为 lib1lib2 部署了某种软件开发工具包。每个 SDK 都包含一些 public headers 以及 lib1lib2 静态库。这两个库都是用 lib3 静态 linked 的,这是一个内部库。

所以 SDK 可能看起来像这样:

lib1 SDK
├── lib
│   ├── lib1.lib
├── headers
│   └── lib1.h

lib2 SDK
├── lib
│   ├── lib2.lib
├── headers
│   └── lib2.h

除客户同时需要 lib1lib2 的情况外,这非常有用。我们的建议是:不要静态 link lib3,而是将其部署在 lib1lib2 SDK 中。在这种情况下,您的客户只需将他们的构建脚本更新为 link 已经包含的 lib3。因此 lib1 客户现在将 link 与 lib1lib3lib2 客户现在 link lib2lib3。您已经将 lib3 部署给客户,只是不是作为 stand-alone 文件,而是包含在 lib1lib2 库中,因此这里没有大的变化。

这意味着同时使用两者的客户可以选择您提供的 lib3 之一,然后 link 反对它。

您的 SDK 现在看起来像这样:

lib2 SDK
├── lib
│   ├── lib2.lib
├── headers
│   └── lib2.h
├── dependencies
│   └── lib3.lib

(same for lib1)

现在存在客户使用 lib1 1.0 的风险,这取决于 lib3 1.0lib2 2.0 这取决于 lib3 2.0,这两个 lib3 版本是二进制兼容的(linking 将成功用于 lib1lib2,而不管 lib3 版本如何),但两者之间有 API 变化lib3 个会产生 运行 时间错误的版本。

在这种情况下,您必须能够在构建时验证兼容性(当您不控制构建过程时更难做到),或者在 运行 时(只要这样做的 lib3 API 不会改变)。

您也可以尝试通过为 lib1lib2 提供通用 SDK 来满足这些客户的需求,该 SDK 始终包含保证与两者兼容的 lib3 版本。但是,这对您来说可能不是一个具有成本效益的策略。

编辑:正如@lalala 所提到的,存在 multi-threaded 可能使这变得不可行的担忧。例如,如果 lib3 不是线程安全的,使 lib1lib2 使用相同的 lib3 将导致竞争条件、死锁等。

我们终于使用动态命名空间解决了问题

首先,为命名空间定义一个宏

#ifndef LIB_NAMESPACE
#define LIB_NAMESPACE SomeNameSpace
#endif

然后在每个 class 周围添加命名空间。

编译时从编译器命令行覆盖宏,例如

g++ -DMY_LIB_NAMESPACE=Lib1Namespace ...
g++ -DMY_LIB_NAMESPACE=Lib2Namespace ...

唯一的缺点是由于重复代码,最终可执行文件的大小会稍大。