2011-07-15 22 views
3

在我正在開發的項目中,我們提供了動態加載附加功能的可能性。爲此,我們使用dlopen。如何查找庫以使用dlopen動態加載它們

爲了找到這個庫,我們有一些我們稱之爲模塊路徑的東西。在那裏,我們有一個默認路徑,其中共享庫是(其中很多是出貨)。

目前我們有兩個默認路徑:我們首先查看共享庫的構建目錄,然後查看安裝目錄。這是因爲它也應該可以在不安裝它的情況下運行應用程序(所以在這種情況下,它需要首先查看構建目錄)。

現在的問題在於,如果用戶從源代碼構建應用程序並使用make install進行安裝,默認情況下將加載她的構建目錄中的庫。這將導致崩潰。因此,只有當用戶之後刪除或重命名構建目錄時纔有效。

沒有問題:是否有一個技巧(通過C++或構建系統)知道應用程序是否安裝。問題是,功能是在一個共享庫中實現的,並且搜索模塊的實現方式也適用於與我們的庫鏈接的其他應用程序(所以我們不能依賴可執行文件的路徑)。我們使用CMake作爲構建系統。

爲了使情況更加困難,解決方案必須在Windows,Linux和Mac OS X上運行

編輯:

我進一步調查,問題更爲複雜。情況是這樣的:

  • 有一個小的可執行一個
  • 此外,還有一個「主」庫main.so
  • 再有就是lib.so
  • lib.so動態加載庫鏈接對main.so

問題是,lib.so具有在它的rpath構建目錄中的main.so的絕對路徑。感謝@MSalters的提示,我現在可以做一個破解,以確保加載正確版本的lib.so(安裝目錄中的那個),但由於它在rpath中有構建路徑,所以加載了錯誤的main .so(因此實際上在內存中有兩個main.so副本 - 這會弄亂一切)。

有沒有辦法從庫中刪除對構建路徑的引用?我嘗試了所有與rpath相關的cmake選項,但沒有成功

+0

是不是很容易修復崩潰呢? – MSalters

+0

問題是,加載的庫鏈接也對主庫。由於構建目錄中的路徑具有到構建目錄中的路徑的完整路徑,並且安裝的路徑中有相對路徑,因此都會加載。然後是衝突(或更具體的:singelton沒有在庫的第二個副本中初始化)。 –

+0

(加載第二個庫)聽起來像你可以很容易地檢測到的東西。這不是你問題的答案嗎? – MSalters

回答

1

難道你不能檢查可執行文件本身在哪裏嗎?如果它在構建目錄中,請使用構建庫 - 如果它在安裝中,請使用install?

getcwd()在所有這些平臺上都有等價物,但它可能不是您想要的 - 這取決於您如何運行可執行文件。

爲了獲得進程的位置,系統特定的,我認爲,但它不應該太難以包裝。

+0

我也想過這個。問題是,我們有一個庫,如果另一個可執行文件鏈接到該庫(例如我們用於測試的另一個可執行文件),則它不再工作。 –

0

安裝的版本不應在rpath中具有構建目錄。

您可能需要執行兩次鏈接(一次爲構建版本,一次爲已安裝版本)。通常,在* nix系統上,安裝的二進制文件有一些靜態路徑,用於查找插件。你可以定義一些環境變量(或命令行參數)來爲構建執行重載它(並使用包裝腳本在構建環境中設置它)。

檢查它是如何解決的一些項目(例如Firefox)。

我對windows系統瞭解不多,但我認爲這樣做的標準方法是在可執行文件的同一目錄中搜索插件。

相關問題