Compiling

編譯時連結boost庫的困惑

  • December 7, 2013

對於一個客戶,我需要在系統中添加 boost 1.54。所以我下載了最新版本(1.55)並將其建構在一個特殊的目錄中:/usr/local/lib/boost1.55/。這行得通。然後我不得不以這種方式調整 Makefile。

LIBS = $(SUBLIBS) -L/usr/lib/x86_64-linux-gnu -LC:/deps/miniupnpc -lminiupnpc -lqrencode -lrt -LC:/deps/boost/stage/lib -Lc:/deps/db/ build_unix -Lc:/deps/ssl -LC:/deps/libqrencode/.libs -lssl -lcrypto -ldb_cxx -L/usr/local/lib/boost1.55/boost_system-mgw46-mt-sd-1_54 -L/usr /local/lib/boost1.55/boost_filesystem-mgw46-mt-sd-1_54 -L/usr/local/lib/boost1.55/boost_program_options-mgw46-mt-sd-1_54 -L/usr/local/lib/boost1 .55/boost_thread-mgw46-mt-sd-1_54 -lQtDBus -lQtGui -lQtCore -lpthread -lboost_system -lboost_filesystem -lboost_program_options -lboost_thread

在未修改的 Makefile 中,boost 連結如下所示:

-lboost_thread-mgw46-mt-sd-1_54

但這沒有用。我無法編譯它,因為它沒有找到。所以我添加了(如您在上面看到的)

-L/usr/local/lib/boost1.55/boost_thread-mgw46-mt-sd-1_54

-lboost_thread

否則它也不會編譯。編譯成功後,我在二進製文件上執行了 ldd ,它顯示:

libboost_system.so.1.53.0 => /usr/lib/x86_64-linux-gnu/libboost_system.so.1.53.0 (0x00007f416c169000) libboost_filesystem.so.1.53.0 => /usr/lib/x86_64-linux-gnu/ libboost_filesystem.so.1.53.0 (0x00007f416bf52000) libboost_program_options.so.1.53.0 => /usr/lib/x86_64-linux-gnu/libboost_program_options.so.1.53.0 (0x00007f416bce4000) libboost_thread.so.1.53.0 => / usr/lib/x86_64-linux-gnu/libboost_thread.so.1.53.0 (0x00007f416bace000)

1.53 是包管理器安裝的版本。我不明白為什麼它連結到這個版本。如果我沒有安裝 1.55,它就不會編譯,但現在它沒有連結到這個版本。對此有何解釋?

實際上我的目標是不使用動態連結庫,我還沒有想出如何做到這一點,但我仍然想知道為什麼上面沒有按預期工作。

您沒有說這是 Linux 的哪個發行版,但通常有一個目錄,您可以在其中添加動態可連結庫。在 Fedora 等 Redhat 發行版上,此目錄位於此處,/etc/ld.so.conf.d/.

LD

您可以使用新安裝的庫的路徑將文件添加到此目錄,如下所示:

$ cat /etc/ld.so.conf.d/myboost.conf
/usr/local/lib/boost1.55

然後執行這個命令:

$ ldconfig -v

這將處理所有庫並重建“記憶體”,/etc/ld.so.cache. 此記憶體用於在指定庫時定位庫,如下所示:-lboost_thread-mgw46-mt-sd-1_54.

範例輸出

$ ldconfig -v
/usr/lib64/atlas:
       libclapack.so.3 -> libclapack.so.3.0
       libptcblas.so.3 -> libptcblas.so.3.0
       libf77blas.so.3 -> libf77blas.so.3.0
       libcblas.so.3 -> libcblas.so.3.0
       liblapack.so.3 -> liblapack.so.3.0
       libptf77blas.so.3 -> libptf77blas.so.3.0
       libatlas.so.3 -> libatlas.so.3.0
/usr/lib64/wxSmithContribItems:
       libwxflatnotebook.so.0 -> libwxflatnotebook.so.0.0.1
...

在為設置添加路徑時,我喜歡通過此輸出進行確認,以確保事情按照我期望的方式進行。

LD的記憶體

您也可以隨時使用以下命令列印 .cache 文件的內容:

$ ldconfig -p | head -10
2957 libs found in cache `/etc/ld.so.cache'
   lib3ds-1.so.3 (libc6,x86-64) => /usr/lib64/lib3ds-1.so.3
   libzvbi.so.0 (libc6,x86-64) => /usr/lib64/libzvbi.so.0
   libzvbi-chains.so.0 (libc6,x86-64) => /usr/lib64/libzvbi-chains.so.0
   libzrtpcpp-1.4.so.0 (libc6,x86-64) => /usr/lib64/libzrtpcpp-1.4.so.0
   libzmq.so.1 (libc6,x86-64) => /usr/lib64/libzmq.so.1
   libzmq.so (libc6,x86-64) => /usr/lib64/libzmq.so
   libzipios.so.0 (libc6,x86-64) => /usr/lib64/libzipios.so.0
   libzipios.so (libc6,x86-64) => /usr/lib64/libzipios.so
   libzip.so.1 (libc6,x86-64) => /usr/lib64/libzip.so.1

為什麼我的 ldd 輸出仍然使用 1.53?

這是因為您的二進製文件正在使用動態庫。所以當二進製文件被編譯時,它是針對 1.55 版本的庫。但是,當您使用 查詢二進製文件時ldd,它位於使用.cache文件內容的環境中。因此,與此二進製文件使用的符號相關聯的記憶體中的庫與 1.53 的庫匹配,因此您會看到這些庫。

您的環境對 1.55 庫一無所知,只有您的建構環境,即您的 Makefile,知道這一點。

動態庫

將這些中的功能視為符號。符號是一個名稱,因此這些名稱通常不會從一個庫版本更改為另一個版本。因此,如果您要查看諸如 boost 之類的庫,您可以使用該工具readelf獲取其中一個.so文件中的符號列表。

例子

$ readelf -Ws /usr/lib64/libboost_date_time-mt.so | head -10

Symbol table '.dynsym' contains 261 entries:
  Num:    Value          Size Type    Bind   Vis      Ndx Name
    0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
    1: 000000335aa096a8     0 SECTION LOCAL  DEFAULT    9 
    2: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZNSt8bad_castD2Ev@GLIBCXX_3.4 (2)
    3: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZNSt6locale5_ImplD1Ev@GLIBCXX_3.4 (2)
    4: 0000000000000000     0 OBJECT  GLOBAL DEFAULT  UND _ZTINSt6locale5facetE@GLIBCXX_3.4 (2)
    5: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND wcslen@GLIBC_2.2.5 (3)
    6: 0000000000000000     0 OBJECT  GLOBAL DEFAULT  UND _ZTISt11logic_error@GLIBCXX_3.4 (2)

在上面的輸出中,您可以看到一些FUNC定義,這些是用於將執行檔中的函式與某個.so庫中的函式“連結”的名稱。

我過度簡化了這一點,並且可能稍微解釋了一些事情,但我只是想讓您大致了解引擎蓋下的機器如何工作的機制。

參考

引用自:https://unix.stackexchange.com/questions/104074