如何链接(或解决)两个定义相同符号的第三方静态库?

时间:2012-11-02 17:02:27

标签: c++ c linker openssl static-libraries

我不可能是唯一遇到这种情况的人。

我有一个C ++应用程序需要链接到SDK中的一个第三方和另一个静态库集。出于某些令人沮丧的原因,SDK将相同的第三方库的子集重新编译为它们自己的(重命名的)lib,尽管这些符号本身的名称相同,并且它们未封装在命名空间中。我的应用程序本身依赖于相同的第三方库。

我考虑了一些选择,但也许我错过了一些东西,希望新面貌能帮到我。也许我很亲密,有人会知道其中一个的下一步。到目前为止,我将列举我尝试过的内容以及每种解决方案的缺点:

  1. 与两者联系。 我得到大约2500行符号重新定义/大小更改警告和错误。这是我第一次发现他们定义了相同的符号。我正在尝试用g ++重新编译OpenSSL并将其放入命名空间中...请参阅下面的编辑...

  2. 仅与SDK链接。 我得到了我自己的代码所依赖的未定义符号 - 这是我发现他们重新编译第三方库是一个子集,或者至少配置了一个模块被禁用。

  3. 仅与第三方lib链接。 我在SDK上报告了一些未定义的符号 - 其中一个实际上是第三方库中头文件中的#define,因此第三方lib中的所有引用都解析为定义,但外部引用却没有。我把它移到c文件中,这解决了这个问题,但是我仍然有两个我在任何地方都找不到的未解决的函数。这是我到目前为止最接近的。

  4. 从一个lib和链接中删除冲突的符号。 到目前为止,这还没有奏效。它可能是SDK中静态链接的lib与我尝试使用第三方库的版本之间的版本问题,但看起来某些函数在符号之间移动,因此通过删除符号,我无意中删除了我在其他地方需要的功能。 SDK中的符号中的函数与第三方lib中的符号中的函数之间似乎没有完美的映射。剥离功能而不必手动调整地址是否合理?

  5. 我一直在用libs检查符号中的符号:

    nm -C --defined-only lib<name>.a
    

    使用以下方法提取整个对象

    ar -x lib<name>.a <objname>.o
    

    希望这也可以帮助那些不得不与彼此冲突的第三方库链接的其他人。为了具体细节,第三方库是OpenSSL,SDK是Opsec - libcpopenssl.a是Opsec中令人讨厌的库。

    **编辑 - 可能的后期入口解决方法可能是使用g ++重新编译OpenSSL并将整个内容放在命名空间中,然后链接两个库。我现在正在尝试......还有更多......

2 个答案:

答案 0 :(得分:3)

Google搜索表明SSL_get_peer_dh和DH_dup确实是来自libcpopenssl.a的添加内容,并且它们在我的OpenSSL副本中也不存在。所以你真的必须链接那个库。在二进制级别将两个库混合在一起(上面的方法4)不太可行 - OpenSSL对它的ABI非常挑剔(他们通常将.so文件版本化为次要编号) )所以你必须非常幸运地拥有一个与他们的.a文件兼容的.so文件。

我的建议是方法4的变体,但在源级别:你将在Opsec libcpopenssl.a中有链接,因为它是OpenSSL的修改版本,包括额外的符号(可能还有其他修改),并抓住您需要从OpenSSL源获得额外的功能,并使用libcpopenssl.a重新编译这些对象,以便他们可以使用Opsec版本中的功能。如果您只使用一些未由libcpopenssl.a导出的OpenSSL函数,那么这是非常可行的。

当然,这仍然是一种繁琐的方法,但它是获得符号兼容性的有保证的方法,当然,前提是Opsec SDK没有对OpenSSL进行语义更改,这将破坏您正在拉入其中的其他OpenSSL功能项目

(我是StackOverflow的新手,所以我不知道这个建议是否有资格作为正确的答案,但无论如何我都没有发表评论的声誉点。如果不合适,我会删除它。)< / p>

答案 1 :(得分:1)

如果您感到好奇,那么在最新版本的OpenSSL中修改了249个文件以进行编译。到目前为止,最常见的问题是大量的C风格指针转换,特别是void *。现在我在梦中看到“reinterpret_cast”。

这并没有单独解决它 - 它仍然需要完整地放入命名空间,这意味着再次修改所有文件以及我自己对它的内部引用。我想我现在要传递这个。

感谢大家的帮助。