2012-11-02 54 views
26

我不能是唯一一個遇到這個問題的人。如何鏈接(或解決)定義相同符號的兩個第三方靜態庫?

我有一個C++應用程序,需要一個第三方,另一個靜態庫在SDK設置鏈接。由於某些令人沮喪的原因,SDK有一個相同的第三方庫的子集重新編譯到它們自己的(重命名的)庫中,儘管這些符號本身被命名爲相同的,並且它們沒有封裝在命名空間中。我的應用程序本身依賴於相同的第三方庫。

我已經考慮了幾個選擇,但也許我失去了一些東西,希望有煥然一新的感覺會幫助我。也許我很接近,有人會知道其中之一的下一步。我將列舉我已經嘗試過的以及每種解決方案迄今爲止的缺點:

  1. 與兩者的鏈接。 我得到大約2500行符號重定義/大小更改警告和錯誤。這是我第一次發現他們定義了相同的符號。我試圖重新編譯的OpenSSL與g ++以及拖放到一個命名空間的那一刻......見下面編輯...

  2. 鏈接只用SDK。 我得到了我自己的代碼依賴的未定義符號 - 這是當我發現他們的第三方庫的重新編譯是一個子集,或者至少配置了一個禁用的模塊。

  3. 鏈接只與第三方庫。 我有幾個由SDK報告的未定義符號 - 其中一個實際上是第三方lib中頭文件中的#define,因此第三方lib中的所有引用都解析爲該定義,但在那裏的引用沒有。我把它移入了c文件,這解決了這個問題,但是我仍然有兩個我在任何地方都找不到的未解決的函數。這是迄今爲止我所得到的最接近的。

  4. 地帶衝突的符號從一個lib和聯繫在兩者。 到目前爲止,這還沒有奏效。它可能是SDK中靜態鏈接庫與我嘗試使用第三方庫的版本之間的版本問題,但它看起來像一些函數在符號之間移動,所以通過刪除符號,我無意中刪除了一個我在其他地方需要的功能。在SDK中的符號函數與第三方庫中的符號函數之間似乎沒有完美的映射。剝離功能而不必手動調整地址是否合理?

我一直在研究符號庫有:

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

而且隨着提取整個對象:

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

希望這也將幫助其他人誰曾與第三鏈接 - 彼此衝突的部分庫。對於細節的緣故,第三方的lib是OpenSSL,和SDK是Opsec - libcpopenssl.a是OPSEC違規庫。

**編輯 - 遲進入可能的解決方法是相剋重新編譯的OpenSSL ++,把整個事情的命名空間,然後鏈接這兩個庫。我正在嘗試...現在更多...

+0

你可以離開opsec openssl衍生物嗎?並且鏈接你的OpenSSL?這聽起來像他們包含了libcopopenssl.a,以防你沒有OpenSSL鏈接。如果他們正確地分離了他們的OpenSSL衍生物,符號應該連線。即鏈接其他lib-set中的所有其他內容,除了*那個lib,並且鏈接OpenSSL。 – WhozCraig

+0

這就是我在上面#3中嘗試過的,基本上。我必須將#define移動到C文件並重新編譯,然後我仍然有兩個未定義的符號。我無法在任何地方找到SSL_get_peer_dh或DH_dup。 – rutgersmike

+0

難道你不能用'nm'腳本來抓取來自* good * OpenSSL的符號。然後去掉這個名字列表的* bad * lib。如果他們有靜態鏈接,那麼內部引用已經解決。或者,如果沒有,使用'-r'或'-Ur'到鏈接器。 –

回答

3

谷歌搜索表明SSL_get_peer_dh和DH_dup真的是來自libcpopenssl.a的新增內容,它們也不存在於我的OpenSSL副本中。所以你真的必須把這個庫鏈接起來。在二進制級別將這兩個庫混合在一起(上面的方法4)不太可能奏效 - OpenSSL對它的ABI非常挑剔(它們通常將.so文件版本化爲次要編號),所以你必須非常幸運才能擁有.so,這與ABI兼容.a文件。

我的建議是方法4的一種變體,但是在源代碼級別:您將在Opsec libcpopenssl.a中有鏈接,因爲它是OpenSSL的一個修改版本,它包含額外的符號(可能還有其他修改)您需要從OpenSSL源中獲得額外的函數,並使用libcpopenssl.a重新編譯這些對象,以便它們可以使用Opsec版本中的函數。如果您只使用一些未由libcpopenssl.a導出的OpenSSL函數,這是非常可行的。當然,如果Opsec SDK沒有對OpenSSL進行語義更改,這將會破壞您要添加的其他OpenSSL功能,但是這是一種保證符號兼容性的有效方法。你的項目。我是新來的StackOverflow,所以我不知道這個建議是否合格,但我沒有聲望點發表評論,如果不合適,我會刪除它。)

+0

我無法在這些功能上找到太多,謝謝!我厭倦了修改OpenSSL,但這是我前往的地方,我將嘗試將它編譯爲C++並將其放入命名空間。當我有更多信息時我會更新。 – rutgersmike

1

如果您對病態好奇,在最新版本的OpenSSL中修改了249個文件以便進行編譯。到目前爲止最常見的問題是豐富的C風格指針轉換,特別是void *。現在我在夢中看到「reinterpret_cast」。

雖然這並沒有解決它 - 它仍然需要被放置到一個名稱空間的整體,這意味着再次修改所有文件以及我自己的內部引用。我想我現在要傳遞這個信息。

感謝大家的幫助。

相關問題