2013-11-02 93 views
3

我找到了一個庫,libjson,我試圖建立一個共享庫並在一個項目中使用。建築很簡單,固定的Makefile錯誤後,如何重命名共享庫以避免同名衝突?

# SHARED=1 make install 

將編譯和/usr/lib安裝.so。問題是我的系統(Arch Linux)已經有一個名爲libjson的庫,Makefile爲我覆蓋了這個庫! Arch的庫被安裝爲依賴項,所以它不能被替換。如果他們有一個名爲libjson的庫,那麼其他發行版可能會有類似的問題。

我該怎麼辦?我可以重新命名圖書館(libjson-mine或其他),但動態鏈接離魔法只有幾步之遙,所以我不知道這是否會破壞某些東西。 如何重命名圖書館?

另一種選擇是將庫的源代碼放到我的當前項目的源代碼樹,並有建設者使靜態庫,而不是。 (很顯然,這會讓我的代碼存儲庫變得更加混亂,因此不太合適)。如果我走這條路線,我需要讓鏈接器更喜歡我的libjson.a,而不是搜索/usr/lib以獲得「合適」(讀取:錯誤)庫。 如何讓鏈接器更喜歡我的版本?

或者,有沒有第三種選擇,我不知道?

+1

一個更好的想法是用通常的'/ usr/local /'前綴來配置和安裝你的軟件包,這樣你的'libjson'會進入'/ usr/local/LIB/libjson.so';另外,瞭解有關'LD_LIBRARY_PATH'環境變量和'/ etc/ld.so.conf'和'ldconfig'命令的更多信息。 –

回答

3

背景概念

共享庫在兩個點用於:

  • 彙編由接頭(ld
  • 執行由動態加載器
  1. 如果在gcc中編譯爲-llibjson,則基本名稱將存儲在可執行文件中

    在執行時,將爲標準路徑搜索該基本名稱。

    在鏈接時,鏈接器必須能夠在其搜索路徑上找到您的庫。這是不容易的前插搜索路徑:

    你也許能夠逃脫/usr/local/lib其意在用戶編譯庫,並應來之前/usr/lib

    但這樣做會破壞任何使用其他libjson,所以你可能不希望出現這種情況。

  2. 如果您在GCC編譯-l:/full/path/to/libjson.so的完整路徑將存儲在可執行文件。

    執行時,不需要路徑搜索,因爲我們已經有完整的路徑。

可檢查存儲在可執行文件:

readelf -d a.out | grep 'Shared library' 

可能的解決方案

我沒有看到,不需要編輯的的Makefile什麼好的解決辦法項目,所以細節是項目特定的。但總體而言,您可以:

  1. 編輯Makefile文件或庫相似,基本名稱重命名爲libjson_mine.so

    編譯需要該庫的程序:-ljson_mine。這將起作用,因爲我們知道/usr/lib.so搜索路徑中。

    這是最好的選擇,遲早要做,否則它將成爲無盡混亂的根源......發送拉請求!

    在相同的拉取請求中,也將默認安裝目錄更改爲/usr/local/lib而不是/usr/lib。這是理智的用戶編譯庫必須默認的地方,完全避免覆蓋分發提供的庫。

  2. 如果所有者不想重命名庫,請在Makefile中找到一個選項來更改生成的庫的基本名稱。

    如果此選項不存在,請求拉取。如果所有者不想接受該項目,則分叉該項目;-)

    然後,您和您的發行版可以在編譯時使用該選項。

  3. 查找Makefile中改變其安裝在庫+頭文件的目錄選項,然後使用一些完全自定義(~/usr/lib~usr/include),並添加到您的動態加載程序的搜索路徑How to specify preference of library path? +包含搜索路徑。有關GNU方法,請參見DESTDIR and PREFIX of make

    然後在編譯/執行時,更改包含/動態加載程序搜索路徑。

    不理想,但可能適用於一次性。

1

有幾種方法:

  • 默認安裝的庫聽起來好像你可以將這些東西與它。想過那個?
  • 也許你確實可以重命名「其他」json庫,並將其安裝到/usr/local/lib
  • 也許你可以學習在Arch Linux上構建一個(pacman?)包。我不知道,但它不應該太難。至少,它不適用於基於RPM的系統,所以我也不在Arch上。
  • 你可以用你的方式在兩者之間去:

    從其他項目中生成靜態庫,包括在自己的項目。這樣你就不會搞亂已安裝的庫,而且你的代碼樹也是乾淨的。

+0

除了其他開發人員可能位於我的其他架構(x86_64)之外,我不介意以最後的方式進行操作,而且目標實際上是運行Yocto Linux的ARM板。 – thirtythreeforty