簡體   English   中英

強制或禁止使用特定的次要版本的libstdc ++

[英]Forcing or preventing use of a particular minor version of libstdc++

為了利用C ++ 11和c ++ 14功能,我有一個使用較新版本的gcc(4.9.1)和較新的libstdc ++編譯的應用程序。 該應用程序由許多小程序組成,因此我將libstdc ++作為共享庫而不是靜態庫進行鏈接(即,我不希望使用-static-libstdc ++)

我希望將新版本的libstdc ++與應用程序一起放在/ opt // lib64下(注意:GPL的例外明確允許這樣做)

libstdc ++。so的新版本與目標平台上的版本僅次要版本不同。 libstdc ++設計為向前兼容,以便現有程序可以使用該庫的新版本。 但是,當某些程序使用新版本而不是舊版本時,我觀察到了行為上的細微差異(即錯誤)。 我希望防止這種情況。

我還發現ld將嘗試將我的應用程序與libstdc ++的系統版本鏈接,除非我將/ opt // lib64放在LD_LIBRARY_PATH的前面。 可以使用-l:<library>.<version>強制鏈接到特定版本,但是,這似乎不起作用。 我懷疑這是針對用戶創建的庫,而不是針對像libstd ++這樣的語言運行時庫,因為gcc本身會生成鏈接描述文件。 同樣在我的目標平台之一(RHEL5)上,gcc / ld甚至不了解它。 我認為可以通過使用-nostdlib並在構建系統中鏈接所需的所有內容(例如-lgcc),而不是將其留給我希望的gcc來實現。 到目前為止,我還沒有嘗試過。

一種簡單的解決方法是確保在我運行應用程序時LD_LIBRARY_PATH包含/ opt // lib64,否則,我可以將LD_PRELOAD與正確的庫版本一起使用。 如果有人決定忽略我的建議並運行,則會出現此問題

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/<vendor>/lib64 

它可能導致難以診斷的問題。 所以我一直在尋找更好的方法。

我想知道是否可以通過某種方式將libstdc ++重命名為lib_stdc ++並鏈接到該soname。 重命名libstdc ++是不夠的,因為您需要按照readelf的要求更改文件中的soname。

0x000000000000000e (SONAME)             Library soname: [libstdc++.so.6]

如果您對使用gcc鏈接的普通程序執行此操作,甚至使用-l:stdc++.so.6.0.20說您會注意到它給出的是主要版本,而不是特定的次要版本。

readelf -d <myapp>
0x0000000e (SONAME)                     Library soname: [libstdc++.so.6]

而不是:

0x0000000e (SONAME)                     Library soname: [libstdc++.so.6.0.20]

因此,我改為使用我想依賴的soname創建了一個虛擬共享庫,以添加依賴關系,如下所示:

gcc dummy.o -Wl,-soname,lib<vendor>_stdc++.so.6.0.20 -nostdlib -shared -o lib<vender>_dummycpp.so

(其中dummy.o是一個空的目標文件,由一個空的源文件制成,以停止-nostdlib導致投訴)

然后:

gcc <myapp> -l<vendor>_dummycpp

根據需要,我現在得到:

readelf -d <myapp>

0x0000000000000001 (NEEDED)             Shared library: [lib<vendor>_stdc++.so.6.0.20]

代替

0x0000000000000001 (NEEDED)             Shared library: [libstdc++.so.6]

dummycpp庫包含libstdc ++中的所有符號,因為它是libstd ++,因此完全不需要gcc與sost libstdc ++鏈接。 我似乎已經完全解決了這個問題。

這讓我感到有點棘手,所以我想在這里提出的問題是:

  • 這是一個好主意嗎?

  • 如果不是,為什么不呢?

  • 有沒有更好/更正確的方法?

注意:如果在RPM中將libstdc ++打包為其他名稱(例如lib_stdc ++。so.6.0.20),則會缺少對它的依賴關系,需要使用--nodeps進行安裝。 這是因為RPM掃描鏈接時間相關性。 解決方法是也安裝虛擬庫。 然后,RPM將從虛擬庫中獲取soname,並且不會聲稱它丟失。

libstdc ++常見問題解答條目如何確保找到動態鏈接的庫,鏈接到手冊部分“ 查找動態或共享庫” ,該部分說明了如何使用RPATH。

我的首選方法是使用$ORIGIN的RPATH,這意味着搜索動態庫依賴項的起始位置與二進制文件所在的目錄相同(請參閱ld.so(8) )。 因此,如果您使用'-Wl,-rpath,$ORIGIN' (請注意用引號防止$ ORIGIN被外殼擴展),則可以將共享庫安裝在與已安裝的二進制文件相同的目錄中,當您使用運行二進制文件。 或者'-Wl,-rpath,$ORIGIN/../lib'如果您希望在某些安裝前綴下使用單獨的binlib目錄'-Wl,-rpath,$ORIGIN/../lib'使用'-Wl,-rpath,$ORIGIN/../lib'

由於庫是在ldconfig不掃描的某些自定義路徑中與二進制文件一起安裝的,並且沒有LD_LIBRARY_PATH破壞環境,因此不應該使用該版本的應用程序將永遠找不到較新的libstdc ++。

請確保您還安裝libstdc++.so.6符號鏈接指向libstdc++.so.6.0.20文件,使DT_NEEDEDlibstdc++.so.6可以找到該文件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM