我之前寫過一篇關於LD_LIBRARY_PATH與gcc/g++ -L的關系的文章,於是我自己用CPACK制作了一個Debian安裝包,然后我在/home/.bashrc里添加了export LD_LIBRARY_PATH=/usr/loca/lib:$LD_LIBRARY_PATH,再然后老大告訴我這個方法不行,打回重新想辦法,經過一番尋找終於找到了---ld.so.conf可以完美解決這個問題。
首先說說,為什么LD_LIBRARY_PATH不行?可以看看老外是怎么說的
一般LD用在下面情況:
- 升級共享庫時,替換之前先測試一下
- 類似的,升級后的某個程序可能依賴於一些動態鏈接庫,如果你將某個鏈接庫替換了,程序可能就無法工作了。這時候,你可以使用LD_LIBRARY_PATH指向存有備份的一個目錄,然后,你可以沒有顧忌地替換系統版本了。萬一出錯,拷貝回去就是了
感覺LD_LIBRARY_PATH就是臨時使用的,為什么呢?因為LD_LIBRARY_PATH如果設置成全局的話,如果被破壞掉的,那么就會出現大規模的破壞。不要說這個變量不會改,但是這樣做就是不妥的辦法,網上大家可以找到許許多多的關於LD_LIBRARY_PATH不好的文章。這里就不再多說
但是,如果不讓用LD_LIBRARY_PATH,我們該怎么辦呢?
Linux系統為大家已經想好了辦法,我們使用ld.so.conf來解決。我們已經知道linux在加載動態庫的時候,會去標准路徑下(/lib,/usr/lib)下去尋找應用程序用到的動態庫。但對於我們那些不標准的路徑下我們安裝了lib庫,例如我把我的庫安裝到了/usr/local/lib下了,我們怎么辦呢?
Linux的通常做法是:將非標准路經加入 /etc/ld.so.conf,然后運行 ldconfig 生成 ld.so.cache。 Linux在加載共享庫的時候,會從 ld.so.cache 查找。[ldconfig需要在root權限下執行]
所以,我們在安裝了庫,但是編譯程序后,ldd發現鏈接不到庫,那么我們就要查看你安裝的庫是否是非標准路徑,如果是那么就把你的非標准路徑加入到/etc/ld.so.conf文件中,然后調用ldconfig生成下ld.so.cache,就可以了。想查看下你的庫是否已經在ld.so.cache中,可以這樣 ldconfig -p | grep lib**就可以了。
對於,Ubuntu來說,還與其他的LINUX系統不一樣,在/etc/ld.so.conf中只有一句include /etc/ld.so.conf.d/*.conf,也就是說它我們不能在/etc/ld.so.conf下添加,但是我們可以在/etc/ld.so.conf.d下新建一個*.conf在這里面添加你的非標准路徑就可以了,記得調用sudo ldconfig 生成ld.so.cache文件就可以了
補充:
說說今天又遇到的問題:(cmake之后出現的問題)
問題1:/usr/bin/ld: warning: libboost_system.so.1.55.0, need by /usr/local/lib/libboost_thread.so, may conflict with libboost_system.so.1.48.0
.....
問題2: `.text._ZN5boost16exceptions_detail10bad_alloc_D2Ev' refereced section `.text._ZN5boost16exceptions_detail10bad_alloc_D1Ev'..... of /usr/lib/gcc/x86_64-linux-gnu/4.8.2/../../../libboost_thread.a(thread.o)
這兩個問題折騰我了一下午,這兩個問題的變現不一樣,其實他們都是一個問題造成的。
首先說說為什么會這樣?
第一個問題:是由於系統里面在/usr/lib下面有一個libboost_system.so.1.48.0,而在/usr/local/lib下我安裝了一個libboost_system.so.1.55.0,造成了g++鏈接時的沖突
第二個問題:是由於在/usr/lib下有一個libboost_thread.a,而我在/usr/local/lib下安裝了libboost_thread.so.1.55.0,造成了g++鏈接的沖突錯誤。
現在問題來了,他們為什么會沖突呢?為什么呢?我們在編譯程序的時候,gcc/g++是怎樣搜索鏈接庫呢?
經過仔細尋找,我們使用 ld --verbose | grep SEARCH_DIR會出現下面的內容
SEARCH_DIR("/usr/i686-linux-gnu/lib32"); SEARCH_DIR("=/usr/local/lib32"); SEARCH_DIR("=/lib32"); SEARCH_DIR("=/usr/lib32"); SEARCH_DIR("=/usr/local/lib/i386-linux-gnu"); SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib/i386-linux-gnu"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib/i386-linux-gnu"); SEARCH_DIR("=/usr/lib");
這就是gcc再編譯的時候,所搜尋的庫文件所在的路徑,所以就出現了上面的問題。當gcc/g++在/usr/lib中發現這些庫之后,就不再搜索了,然后就讓gcc/g++鏈接了這些庫,而我需要的正確的庫應該在/usr/local/lib下,這就造成了鏈接了錯誤的庫文件。
解決方法就是:刪除掉/usr/lib下同名的不需要的或者版本過低的庫文件(目前是這樣做的,也許有更好的方法,知道的請告訴我)
上面查看gcc/g++/ld搜索路徑還有其他方法:
gcc -Wl, --verbose
gcc --print-search-dirs