usr/bin/ld: cannot find 錯誤解決方法和 /etc/ld.so.conf


 我makefile出現這個錯誤:

HelloWorldServer.c:(.text+0xaa): undefined reference to `zmq_send'
collect2: error: ld returned 1 exit status
make: *** [HelloWorldServer] Error 1

一直以為沒找到動態庫,但是指定了具體路徑:

LDFLAGS=  -L /opt/zeromq/lib -lzmq

$(CC)  $(CFLAGS) $(LDFLAGS) -o $@ $^  

為什么還是報錯???

改正:要把動態庫放在-o 后面,這樣就對了。

 $(CC)  $(CFLAGS)  -o $@ $^  $(LDFLAGS) 可以編譯。

 

 

 

gcc測試動態庫

gcc -lmysqlcient形式。

ldconfig -v列出所有可用的動態庫

通常在軟件編譯時出現的usr/bin/ld: cannot find -lxxx的錯誤,主要的原因是庫文件並沒有導入的ld檢索目錄中。

 

   解決方式:

 

  1。確認庫文件是否存在,比如-l123, 在/usr/lib, /usr/local/lib,或者其他自定義的lib下有無lib123.so, 如果只是存在lib123.so.1,

       那么可以通過ln -sv lib123.so.1   lib123.so,建立一個連接重建lib123.so.

 

   2。檢查/etc/ld.so.conf中的庫文件路徑是否正確,如果庫文件不是使用系統路徑,/usr/lib, /usr/local/lib, 那么必須在文件中加入。

 

   3。ldconfig 重建ld.so.cache文件,ld的庫文件檢索目錄存放文件。尤其剛剛編譯安裝的軟件,必須運行ldconfig,才能將新安裝的

庫文件導入ld.so.cache.

 

   4。測試,gcc -l123 --verbose.

 

 

/etc/ld.so.conf文件

 

Linux 系統上有兩類根本不同的 Linux 可執行程序。第一類是靜態鏈接的可執行程序。靜態可執行程序包含執行所需的所有函數 — 換句話說,它們是“完整的”。因為這一原因,靜態可執行程序不依賴任何外部庫就可以運行。

  第二類是動態鏈接的可執行程序。

  靜態可執行程序與動態可執行程序比較

  我們可以用 ldd 命令來確定某一特定可執行程序是否為靜態鏈接的:
  # ldd /sbin/sln
  not a dynamic executable
  “not a dynamic executable”是 ldd 說明 sln 是靜態鏈接的一種方式。現在,讓我們比較 sln 與其非靜態同類 ln 的大小:
  # ls -l /bin/ln /sbin/sln
  -rwxr-xr-x    1 root     root        23000 Jan 14 00:36 /bin/ln
  -rwxr-xr-x    1 root     root       381072 Jan 14 00:31 /sbin/sln
  如您所見,sln 的大小超過 ln 十倍。ln 比 sln 小這么多是因為它是動態可執行程序。動態可執行程序是不完整的程序,它依靠外部共享庫來提供運行所需的許多函數。

  動態鏈接相關性

  要查看 ln 依賴的所有共享庫的列表,可以使用 ldd 命令:
  # ldd /bin/ln
  libc.so.6 => /lib/libc.so.6 (0x40021000)
  /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

  如您所見,ln 依賴外部共享庫 libc.so.6 和 ld-linux.so.2。通常,動態鏈接的程序比其靜態鏈接的等價程序小得多。不過,靜態鏈接的程序可以在某些低級維護任務中發揮作用。例如,sln 是修改位於 /lib 中的不同庫符號鏈接的極佳工具。但通常您會發現幾乎所有 Linux 系統上的可執行程序都是某種動態鏈接的變體。

  動態裝入器

  那么,如果動態可執行程序不包含運行所需的所有函數,Linux 的哪部分負責將這些程序和所有必需的共享庫一起裝入,以使它們能正確執行呢?答案是動態裝入器(dynamic loader),它實際上是您在 ln 的 ldd 清單中看到的作為共享庫相關性列出的 ld-linux.so.2 庫。動態裝入器負責裝入動態鏈接的可執行程序運行所需的共享庫。現在,讓我們迅速查看一下動態裝入器如何在系統上找到適當的共享庫。

  ld.so.conf

  動態裝入器找到共享庫要依靠兩個文件 — /etc/ld.so.conf 和 /etc/ld.so.cache。如果您對 /etc/ld.so.conf 文件進行 cat 操作,您可能會看到一個與下面類似的清單:

  $ cat /etc/ld.so.conf

  /usr/X11R6/lib

  /usr/lib/gcc-lib/i686-pc-linux-gnu/2.95.3

  /usr/lib/mozilla

  /usr/lib/qt-x11-2.3.1/lib

  /usr/local/lib

  ld.so.conf 文件包含一個所有目錄(/lib 和 /usr/lib 除外,它們會自動包含在其中)的清單,動態裝入器將在其中查找共享庫。

  ld.so.cache

  但是在動態裝入器能“看到”這一信息之前,必須將它轉換到 ld.so.cache 文件中。可以通過運行 ldconfig 命令做到這一點:

  # ldconfig

  當 ldconfig 操作結束時,您會有一個最新的 /etc/ld.so.cache 文件,它反映您對 /etc/ld.so.conf 所做的更改。從這一刻起,動態裝入器在尋找共享庫時會查看您在 /etc/ld.so.conf 中指定的所有新目錄。
   

  ldconfig 技巧
   

  要查看 ldconfig 可以“看到”的所有共享庫,請輸入:
   

  # ldconfig -p | less

  還有另一個方便的技巧可以用來配置共享庫路徑。有時候您希望告訴動態裝入器在嘗試任何 /etc/ld.so.conf 路徑以前先嘗試使用特定目錄中的共享庫。在您運行的較舊的應用程序不能與當前安裝的庫版本一起工作的情況下,這會比較方便。

  LD_LIBRARY_PATH

  要指示動態裝入器首先檢查某個目錄,請將 LD_LIBRARY_PATH 變量設置成您希望搜索的目錄。多個路徑之間用冒號分隔;例如:

  # export LD_LIBRARY_PATH="/usr/lib/old:/opt/lib"

  導出 LD_LIBRARY_PATH 后,如有可能,所有從當前 shell 啟動的可執行程序都將使用 /usr/lib/old 或 /opt/lib 中的庫,如果仍不能滿足一些共享庫相關性要求,則轉回到 /etc/ld.so.conf 中指定的庫。

http://blog.csdn.net/yyyzlf/article/details/5283885

 

LD_LIBRARY_PATH

  Linux環境變量名,該環境變量主要用於指定查找共享庫(動態鏈接庫)時除了默認路徑之外的其他路徑。(該路徑在默認路徑之前查找)
  移植程序時的經常碰到需要使用一些特定的動態庫,而這些編譯好的動態庫放在我們自己建立的目錄里,這時可以將這些目錄設置到LD_LIBRARY_PATH中。
  當執行函數動態鏈接.so時,如果此文件不在缺省目錄下‘/usr/local/lib’ and ‘/usr/lib’.
  那么就需要指定環境變量 LD_LIBRARY_PATH
  假如現在需要在已有的環境變量上添加新的路徑名,則采用如下方式:
  LD_LIBRARY_PATH=NEWDIRS:$LD_LIBRARY_PATH.(newdirs是新的路徑串)
 
 
Linux 運行的時候,是如何管理共享庫(*.so)的?在 Linux 下面,共享庫的尋找和加載是由 /lib/ld.so 實現的。 ld.so 在標准路經(/lib, /usr/lib) 中尋找應用程序用到的共享庫。

但是,如果需要用到的共享庫在非標准路經,ld.so 怎么找到它呢?

目前,Linux 通用的做法是將非標准路經加入 /etc/ld.so.conf,然后運行 ldconfig 生成 /etc/ld.so.cache。 ld.so 加載共享庫的時候,會從 ld.so.cache 查找。

傳統上,Linux 的先輩 Unix 還有一個環境變量:LD_LIBRARY_PATH 來處理非標准路經的共享庫。ld.so 加載共享庫的時候,也會查找這個變量所設置的路經。
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./lib
export LD_LIBRARY_PATH
但是,有不少聲音主張要避免使用 LD_LIBRARY_PATH 變量,尤其是作為全局變量。這些聲音是:
* LD_LIBRARY_PATH is not the answer -  http://prefetch.net/articles/linkers.badldlibrary.html
* Why LD_LIBRARY_PATH is bad -  http://xahlee.org/UnixResource_dir/_/ldpath.html
* LD_LIBRARY_PATH - just say no -  http://blogs.sun.com/rie/date/20040710
解決這一問題的另一方法是在編譯的時候通過 -R<path> 選項指定 run-time path。



1. 往/lib和/usr/lib里面加東西,是不用修改/etc/ld.so.conf的,但是完了之后要調一下ldconfig,不然這個library會找不到

2. 想往上面兩個目錄以外加東西的時候,一定要修改/etc/ld.so.conf,然后再調用ldconfig,不然也會找不到
比如安裝了一個mysql到/usr/local/mysql,mysql有一大堆library在/usr/local/mysql/lib下面,這時就需要在/etc/ld.so.conf下面加一行/usr/local/mysql/lib,保存過后ldconfig一下,新的library才能在程序運行時被找到。

3. 如果想在這兩個目錄以外放lib,但是又不想在/etc/ld.so.conf中加東西(或者是沒有權限加東西)。那也可以,就是export一個全局變量LD_LIBRARY_PATH,然后運行程序的時候就會去這個目錄中找library。一般來講這只是一種臨時的解決方案,在沒有權限或臨時需要的時候使用。

4. ldconfig做的這些東西都與運行程序時有關,跟編譯時一點關系都沒有。編譯的時候還是該加-L就得加,不要混淆了。

5. 總之,就是不管做了什么關於library的變動后,最好都ldconfig一下,不然會出現一些意想不到的結果。不會花太多的時間,但是會省很多的事。


LD_LIBRARY_PATH 這個環境變量是大家最為熟悉的,它告訴loader:在哪些目錄中可以找到共享庫。可以設置多個搜索目錄,這些目錄之間用冒號分隔開。在linux下,還提供了另外一種方式來完成同樣的功能,你可以把這些目錄加到/etc/ld.so.conf中,然后調用ldconfig。當然,這是系統范圍內全局有效的,而環境變量只對當前shell有效。按照慣例,除非你用上述方式指明,loader是不會在當前目錄下去找共享庫的,正如shell不會在當前目前找可執行文件一樣。
 
 
庫搜索路徑的確定有很多方法,LD_LIBRARY_PATH只是其中一種。如編譯命令行rpath參數.   連接時的LD_RUN_PATH環境變量。/lib,/usr/lib標准目錄。動態連接器緩存/etc/ld.so.conf.  
 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM