簡體   English   中英

如何使用 g++ 靜態鏈接除少數庫之外的所有庫?

[英]How to statically link all libraries except a few using g++?

我有一個要求,我靜態鏈接我的所有庫,包括 libstdc++、libc、pthread 等。我想動態鏈接一個omniorb 庫。

目前我已經動態鏈接了所有的庫。 ldd 顯示以下內容

linux-vdso.so.1 =>  (0x00007fff251ff000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f291cc47000)
libomniDynamic4.so.1 (0x00007f291c842000)
libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007f291c536000)
libm.so.6 => /lib64/libm.so.6 (0x00007f291c2e0000)
libgomp.so.1 => /usr/lib64/libgomp.so.1 (0x00007f291c0d7000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f291bebf000)
libc.so.6 => /lib64/libc.so.6 (0x00007f291bb66000)
/lib64/ld-linux-x86-64.so.2 (0x00007f291ce63000)
librt.so.1 => /lib64/librt.so.1 (0x00007f291b95d000)
libomniORB4.so.1 (0x00007f291b6aa000)
libomnithread.so.3 (0x00007f291cf35000

我需要 ldd 將 libomniDynamic4.so.1 顯示為唯一的動態鏈接庫。

我如何實現這一目標?

試圖制作在所有發行版上運行的 linux 可執行文件是嗎? 祝你好運……但我離題了……

您想查看 g++ 的-v標志 output。 它顯示了 g++/ld 執行的內部鏈接命令。 具體來說,您需要檢查最終的鏈接命令collect2及其所有 arguments。 然后,您可以指定要鏈接的 .a 庫的確切路徑。 您還必須跟蹤所有內容的 static 庫。 我的 libstdc++.a 在/usr/lib/gcc/x86_64-linux-gnu/4.4/libstdc++.a

咆哮:我對 linux 最大的抱怨是可執行文件的 state 斷裂。 為什么我不能在一台機器上編譯二進制文件並將其復制到另一台機器上並運行它? 即使是 Ubuntu 發行版分開一個發行版也會產生由於 libc/libstdc++ ABI 不兼容而無法在另一個發行版上運行的二進制文件

編輯#1我只是想添加這個頁面上的腳本會生成一個可執行文件.so 依賴項的.png。 嘗試執行您描述的操作時,這非常有用。

請注意ldd <exename>將列出鏈中的所有依賴項,而不僅僅是可執行文件的直接依賴項。 因此,即使您的可執行文件僅依賴於 omniorb.so,但 omniorb.so 依賴於 libphread.so, ldd的 output 也會列出這一點。 查找readelf的手冊頁以僅查找二進制文件的直接依賴項。

另一個需要注意的項目。 如果 omniorb.so 依賴於 libstdc++.so,那么您別無選擇,只能依賴於同一個 lib。 否則 ABI 不兼容將破壞您的代碼和omniorb 代碼之間的RTTI。

我需要 ldd 將 libomniDynamic4.so.1 顯示為唯一的動態鏈接庫。

那是不可能的。

首先,對於需要動態鏈接的任何 ( x86_64 ) 二進制文件, ldd始終顯示ld-linux-x86-64.so.2 如果您使用動態鏈接(您將使用libomniDynamic4.so.1 ),那么您獲得ld-linux-x86-64.so.2

其次, linux-vdso.so.1被 kernel “注入”到您的進程中。 也無法擺脫它。

接下來,問題是為什么要盡量減少動態庫的使用。 最常見的原因通常是錯誤地認為“大部分是靜態的”二進制文件更便攜,並且可以在更多系統上運行。 在 Linux 上,這與事實相反。

如果實際上您正在嘗試實現可移植二進制文件,則存在幾種方法。 迄今為止最好的一個(根據我的經驗)是使用apgcc

構建在許多 Linux 發行版上運行的單個二進制文件非常困難,並且靜態鏈接不是關鍵點。

請注意,使用較舊的 glibc 版本構建的二進制文件(即舊的 Linux 發行版)也可以在較新的 Linux 發行版上運行。 這是因為 glibc 是向后兼容的。

達到預期結果的一種可能方法是:

  • 在舊的 Linux 操作系統上編譯二進制文件

  • 在二進制文件上使用命令 ldd 或 lsof(運行時)找出編譯后的二進制文件所需的所有庫,詳情請點擊此處

  • 將舊 Linux 操作系統所需的庫復制到“ custom-lib ”文件夾中

  • 始終將這個custom-lib文件夾與您的二進制文件捆綁/發布

  • 創建一個 bash 腳本,將custom-lib文件夾放在LD_LIBRARY_PATH環境變量中文件夾列表的頂部,然后調用您的二進制文件。

通過這種方式,通過使用 bash 腳本執行二進制文件,我能夠在各種不同 Linux 版本的嵌入式設備上執行二進制文件。 但是總是有問題的情況下失敗了。

請注意,我總是使用 cli 應用程序/二進制文件對此進行測試。

其他可能的方式..

似乎也有一些優雅的方法來編譯與 glibc-back 兼容的二進制文件,例如似乎可以編譯與舊 ABI 兼容的二進制文件。 但我沒有檢查過這條路線。

鏈接時,在指定要靜態鏈接到的庫之前使用-static,在要動態鏈接到的庫之前使用-dynamic。 您最終應該得到一個如下所示的命令行:

g++ <other options here> -dynamic -lomniDynamic4 -static -lpthread -lm -lgomp <etc>

當然,您需要.a 您想要靜態鏈接的庫的版本(duh)。

暫無
暫無

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

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