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

时间:2023-01-27 02:37:58

I can't be the only one to run into this.

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

I have a C++ application that needs to link with one third-party and another static library set in an SDK. The SDK has, for some hideously frustrating reason, recompiled a subset of that same third-party library into their own (renamed) lib, although the symbols themselves are named the same and they are not encapsulated within a namespace. My application itself depends upon the same third-party library.

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

I've considered a few options, but maybe I'm missing something and hopefully a fresh look will help me out. Perhaps I'm close and someone will know the next step for one of these . I'll enumerate what I've tried and the shortcomings of each solution so far:

我已经考虑了一些选择,但也许我错过了一些东西,希望新的眼光能帮助我。也许我已经很接近了,有人会知道其中一个的下一步。我将列举我所尝试过的,以及到目前为止每个解决方案的缺点:

  1. Link with both. I get about 2500 lines of symbol redefinition / size change warnings and errors. This is when I first found that they defined the same symbols. I'm trying to recompile OpenSSL with g++ and drop it into a namespace at the moment...see edit below...

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

  2. Link with the SDK only. I get undefined symbols that my own code depends upon - this is when I found that their recompile of the third party lib is a subset, or at least was configured with one module disabled.

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

  3. Link with the third party lib only. I have a couple of undefined symbols reported by the SDK - one of them is actually a #define in a header file within the third party lib, so all references in the third party lib resolve to the definition, but references outside there do not. I moved that into the c file, which resolves that, however I still have two unresolved functions I can't find anywhere. This is the closest I've gotten so far.

    只与第三方库链接。我有两个由SDK报告的未定义的符号——其中一个实际上是在第三方库的头文件中定义的#,所以第三方库中的所有引用都解析为定义,而外部引用则没有。我将它移动到c文件中,它解决了这个问题,但是我仍然有两个无法解析的函数,我在任何地方都找不到。这是我到目前为止最接近的一次。

  4. Strip conflicting symbols from one lib and link in both. So far this hasn't worked. It could be a version issue between the lib statically linked in the SDK and the versions I've tried using of the third-party lib, but it looks like some functions were moved between symbols, so by removing a symbol, I inadvertently remove a function that I need elsewhere. There doesn't seem to be a perfect mapping between functions in symbols in the SDK vs functions in symbols in the third-party lib. Is it plausible to strip functions without having to manually adjust addresses?

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

I've been examining symbols in libs with:

我一直在用libs检查符号:

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

And extracting entire objects with:

并通过:

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

Hopefully this will also help others who have had to link with third-party libs that conflict with one another. For the sake of specifics, the third-party lib is OpenSSL, and the SDK is Opsec - libcpopenssl.a is the offending lib in Opsec.

希望这也能帮助那些不得不与相互冲突的第三方libs链接的其他人。为了具体起见,第三方lib是OpenSSL,而SDK是Opsec - libcpopenssl。a是Opsec中的违规库。

**EDIT- A late entry possible workaround may be to recompile OpenSSL with g++ and put the whole thing in a namespace, and then link both libs. I'm trying that now...more to come...

** *编辑——一个很晚的解决方案可能是使用g++重新编译OpenSSL,并将整个内容放在一个名称空间中,然后链接两个libs。我在现在…更多的来…

2 个解决方案

#1


3  

A Google search indicate that SSL_get_peer_dh and DH_dup are really additions from libcpopenssl.a, and they don't exist in my copy of OpenSSL either. So you'll really have to link that library in. Mixing both libraries together (Approach 4 above) at binary level is unlikely to work -- OpenSSL is very picky about its ABI (they usually have .so files versioned down to the minor number) so you'd have to be very lucky to have an .so that's ABI-compatible to their .a file.

谷歌搜索表明SSL_get_peer_dh和DH_dup实际上是从libcpopenssl中添加的。a,它们也不存在于我的OpenSSL副本中。所以你必须把这个库连接起来。将两个库混合在一起(上面的方法4)在二进制级别上是不可能工作的——OpenSSL对它的ABI非常苛刻(它们通常都有这样的文件),所以你必须非常幸运地拥有一个这样的文件。

My suggestion is a variation of Approach 4, but at source level: you'll have link in the Opsec libcpopenssl.a, since it's a modified version of OpenSSL which include extra symbols (and possibly other modifications), and grab the extra functions you need from the OpenSSL sources and recompile those objects with libcpopenssl.a, so they can use the functions from the Opsec version. If you're only using a few OpenSSL functions which are not exported by libcpopenssl.a, this is quite doable.

我的建议是方法4的变体,但在源代码级别:您将在Opsec libcpopenssl中有链接。a,因为它是一个修改后的OpenSSL版本,包含额外的符号(可能还有其他修改),并且从OpenSSL源代码中获取所需的额外函数,并使用libcpopenssl重新编译这些对象。所以他们可以使用Opsec版本的函数。如果您只使用一些OpenSSL函数,而这些函数不是由libcpopenssl导出的。a,这很可行。

Granted, that's still a cumbersome approach, but it's a guaranteed way to get symbol compatibility, provided of course that the Opsec SDK didn't make semantic changes to OpenSSL that will break the additional OpenSSL functions that you're pulling into your project.

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

(I'm new at * so I don't know if this suggestion qualifies as a proper answer, but I don't have reputation points to post comments, anyway. I'll remove this if it's inappropriate.)

(我是*的新成员,所以我不知道这个建议是否可以作为一个合适的答案,但是我并没有什么好名声。如果不合适的话,我就把它去掉。

#2


1  

If you're morbidly curious, 249 files were modified in the most recent version of OpenSSL to get it to compile. The most common issue by far was the abundance of C-style pointer casts, particularly with void*. Now I see "reinterpret_cast" in my dreams.

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

This didn't solve it alone though - it still needs to be placed into a namespace in its entirety, which means modifying all of the files again as well as my own internal references to it. I think I'm going to pass on this for now.

但这并不是单独解决的——它仍然需要完全放在一个名称空间中,这意味着再次修改所有文件以及我自己对它的内部引用。我想我现在就把这个讲完。

Thanks for the help everyone.

谢谢大家的帮助。

#1


3  

A Google search indicate that SSL_get_peer_dh and DH_dup are really additions from libcpopenssl.a, and they don't exist in my copy of OpenSSL either. So you'll really have to link that library in. Mixing both libraries together (Approach 4 above) at binary level is unlikely to work -- OpenSSL is very picky about its ABI (they usually have .so files versioned down to the minor number) so you'd have to be very lucky to have an .so that's ABI-compatible to their .a file.

谷歌搜索表明SSL_get_peer_dh和DH_dup实际上是从libcpopenssl中添加的。a,它们也不存在于我的OpenSSL副本中。所以你必须把这个库连接起来。将两个库混合在一起(上面的方法4)在二进制级别上是不可能工作的——OpenSSL对它的ABI非常苛刻(它们通常都有这样的文件),所以你必须非常幸运地拥有一个这样的文件。

My suggestion is a variation of Approach 4, but at source level: you'll have link in the Opsec libcpopenssl.a, since it's a modified version of OpenSSL which include extra symbols (and possibly other modifications), and grab the extra functions you need from the OpenSSL sources and recompile those objects with libcpopenssl.a, so they can use the functions from the Opsec version. If you're only using a few OpenSSL functions which are not exported by libcpopenssl.a, this is quite doable.

我的建议是方法4的变体,但在源代码级别:您将在Opsec libcpopenssl中有链接。a,因为它是一个修改后的OpenSSL版本,包含额外的符号(可能还有其他修改),并且从OpenSSL源代码中获取所需的额外函数,并使用libcpopenssl重新编译这些对象。所以他们可以使用Opsec版本的函数。如果您只使用一些OpenSSL函数,而这些函数不是由libcpopenssl导出的。a,这很可行。

Granted, that's still a cumbersome approach, but it's a guaranteed way to get symbol compatibility, provided of course that the Opsec SDK didn't make semantic changes to OpenSSL that will break the additional OpenSSL functions that you're pulling into your project.

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

(I'm new at * so I don't know if this suggestion qualifies as a proper answer, but I don't have reputation points to post comments, anyway. I'll remove this if it's inappropriate.)

(我是*的新成员,所以我不知道这个建议是否可以作为一个合适的答案,但是我并没有什么好名声。如果不合适的话,我就把它去掉。

#2


1  

If you're morbidly curious, 249 files were modified in the most recent version of OpenSSL to get it to compile. The most common issue by far was the abundance of C-style pointer casts, particularly with void*. Now I see "reinterpret_cast" in my dreams.

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

This didn't solve it alone though - it still needs to be placed into a namespace in its entirety, which means modifying all of the files again as well as my own internal references to it. I think I'm going to pass on this for now.

但这并不是单独解决的——它仍然需要完全放在一个名称空间中,这意味着再次修改所有文件以及我自己对它的内部引用。我想我现在就把这个讲完。

Thanks for the help everyone.

谢谢大家的帮助。