我認爲Linux中的一個主要設計缺陷是共享對象地獄,當涉及到分發程序而不是源代碼形式。在運行時加載Linux庫
這裏是我的具體問題:我想發佈一個ELF二進制形式的Linux程序,它應該儘可能多地運行在發佈版本上,所以我的強制性依賴性如此低:在任何情況下所需的唯一庫是libpthread ,libX11,librt和libm(當然還有glibc)。當我使用gcc構建我的程序時,我正在動態鏈接這些庫。
但是,我的程序還應該支持ALSA(聲音接口),Xcursor,Xfixes和Xxf86vm擴展以及GTK。但是這些只能在用戶系統上可用時使用,否則我的程序仍應運行,但功能有限。例如,如果GTK不在那裏,我的程序將回退到終端模式。因爲我的程序仍然可以在沒有ALSA,Xcursor,Xfixes等的情況下運行,所以我不能動態鏈接這些庫,因爲如果其中一個庫不存在,那麼程序根本無法啓動。
所以我需要手動檢查庫是否存在,然後使用dlopen()逐個打開它們,並使用dlsym()導入必要的函數符號。然而,這會導致各種問題:
1)庫命名約定: 共享對象往往不是簡單地稱爲「libXcursor.so」,但有某種版本的擴展,如「libXcursor.so的。 1「,甚至像」libXcursor.so.0.2000「這樣的非常有趣的東西。這些擴展名似乎因系統而異。所以在調用dlopen()時應該選擇哪一個?在這裏使用硬編碼名稱似乎是一個非常糟糕的主意,因爲名稱因系統而異。因此,我想到的唯一解決方法是掃描整個庫路徑並查找以「libXcursor.so」前綴開頭的文件名,然後執行一些自定義版本匹配。但我怎麼知道他們真的兼容?
2)庫搜索路徑:我應該在哪裏查找* .so文件?這也是不同的系統。有一些默認路徑,如/ usr/lib和/ lib,但* .so文件也可能在很多其他路徑中。所以我必須打開/etc/ld.so.conf並解析它以找出所有庫搜索路徑。這並不是一件小事,因爲/etc/ld.so.conf文件也可以使用某種包括指令,這意味着我必須解析更多的.conf文件,對由循環引起的可能的無限循環進行一些檢查包括指令等。真的沒有更簡單的方法來找出* .so的搜索路徑嗎?
所以,我的實際問題是:是不是有一種更方便,不太方便的方式來實現我想要做的事情?創建一個有ALSA,GTK,libXcursor等一些可選依賴項的Linux程序真的很複雜......但是如果沒有它,它也應該可以工作!有什麼樣的標準去做我想做的事情?還是我註定要做這種駭人的方式?
感謝您的意見/解決方案!
您是否考慮構建自己的共享庫?這些可以與您需要的系統庫動態鏈接,可以在您期望的位置,並且可以知道您的名字。 – Hasturkun 2013-04-11 15:22:37
此外,你可能想看看這個問題:http://stackoverflow.com/questions/2827181/dynamic-loading-of-shared-objects-using-dlopen?rq=1 – Hasturkun 2013-04-11 15:38:27
@ 1:對,這可能是一個解決方法,但我必須分發我的應用程序伴隨* .so文件。我希望在我的發行版中只有一個ELF二進制文件。 – Andreas 2013-04-11 15:47:43