简体   繁体   English

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

[英]How can I link with (or work around) two third-party static libraries that define the same symbols?

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. 我有一个C ++应用程序需要链接到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. 出于某些令人沮丧的原因,SDK将相同的第三方库的子集重新编译为它们自己的(重命名的)lib,尽管这些符号本身的名称相同,并且它们未封装在命名空间中。 My application itself depends upon the same third-party library. 我的应用程序本身依赖于相同的第三方库。

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. 我得到大约2500行符号重新定义/大小更改警告和错误。 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... 我正在尝试用g ++重新编译OpenSSL并将其放入命名空间...请参阅下面的编辑...

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

  3. Link with the third party lib only. 仅与第三方lib链接。 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. 我在SDK上报告了一些未定义的符号 - 其中一个实际上是第三方库中头文件中的#define,因此第三方lib中的所有引用都解析为定义,但外部引用却没有。 I moved that into the c file, which resolves that, however I still have two unresolved functions I can't find anywhere. 我把它移到c文件中,这解决了这个问题,但是我仍然有两个我在任何地方都找不到的未解决的函数。 This is the closest I've gotten so far. 这是我到目前为止最接近的。

  4. Strip conflicting symbols from one lib and link in both. 从两个lib和链接中删除冲突的符号。 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. 它可能是SDK中静态链接的lib与我尝试使用第三方库的版本之间的版本问题,但看起来某些函数在符号之间移动,因此通过删除符号,我无意中删除了我在其他地方需要的功能。 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. SDK中的符号中的函数与第三方lib中的符号中的函数之间似乎没有完美的映射。 Is it plausible to strip functions without having to manually adjust addresses? 剥离功能而不必手动调整地址是否合理?

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. 为了具体细节,第三方lib是OpenSSL ,SDK是Opsec - libcpopenssl.a是Opsec中令人讨厌的lib。

**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. **编辑 - 可能的后期入口解决方法可能是使用g ++重新编译OpenSSL并将整个内容放在命名空间中,然后链接两个库。 I'm trying that now...more to come... 我现在正在尝试......更多来......

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

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. 我的建议是方法4的变体,但在源级别:你将在Opsec libcpopenssl.a中有链接,因为它是OpenSSL的修改版本,包括额外的符号(可能还有其他修改),并抓住额外的功能你需要来自OpenSSL源并使用libcpopenssl.a重新编译这些对象,因此他们可以使用Opsec版本中的函数。 If you're only using a few OpenSSL functions which are not exported by libcpopenssl.a, this is quite doable. 如果您只使用了一些未由libcpopenssl.a导出的OpenSSL函数,那么这是非常可行的。

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

If you're morbidly curious, 249 files were modified in the most recent version of OpenSSL to get it to compile. 如果您感到好奇,那么在最新版本的OpenSSL中修改了249个文件以进行编译。 The most common issue by far was the abundance of C-style pointer casts, particularly with void*. 到目前为止,最常见的问题是大量的C风格指针转换,特别是void *。 Now I see "reinterpret_cast" in my dreams. 现在我在梦中看到“reinterpret_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. 感谢大家的帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何解决第三方库中的C4505警告问题? - How can I work around warning C4505 in third party libraries? 与Qt第三方库静态链接 - Static linking with Qt third-party libraries 当两个Linux第三方库在枚举中使用相同的名称时在C ++中做什么 - What to do in C++ when two Linux third-party libraries are using the same names in their enumerations 当两个共享库依赖于以不同方式编译的第三方的相同版本时该怎么办? - What to do when two shared libraries depend on the same version of a third-party compiled differently? g ++不链接第三方库 - g++ does not link third-party libraries 如何在GitHub存储库的Team Services构建中链接到第三方库(.lib)? - How to link against third-party libraries (.lib) in Team Services build of GitHub repo? 如何解决两个不使用命名空间的第三方库之间的类名冲突? - How to resolve class-name conflicts between two third-party libraries that do not use namespaces? 如何在一个代码库中支持两个版本不同命名空间的第三方库 - How to support two versions of third-party libraries with different namespaces in onecodebase 第三方库怎么能做标准库做不到的事情呢? - How can third-party libraries do things that the standard library can't do? 我应该在哪里放置第三方库? - Where should I put third-party libraries?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM