動態庫的麻煩之處

動態庫的麻煩之處在於 - 若是你的程序使用了成百上千個動態庫,你的程序在運行時如何找到這些動態庫? html

通常有三個方法:網絡

1、設置LD_LIBRARY_PATHapp

export LD_LIBRARY_PATH="/path/to/lib"

直接手工設是不可能完成的任務,由於你也知道有不少path (多不是問題,問題時你得知道這些path),因此通常須要在由編譯系統來自動產生這些path,並放到一個runscript中:工具

#set path
export LD_LIBRARY_PATH=/path/to/lib1
export LD_LIBRARY_PATH=/path/to/lib2:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=/path/to/lib3:$LD_LIBRARY_PATH
# ...
export LD_LIBRARY_PATH=/path/to/lib100:$LD_LIBRARY_PATH

# run app
/path/to/myapp

 

2、設置rpathpost

rpath設置能夠在編譯時:ui

g++ -Wl,-rpath,/path/to/lib ...
or
ld -rpath /path/to/lib ...

rpath應該能夠是-L一致,因此能夠在編譯系統中作些工做自動產生rpath,premake目前(4.4beta)還不支持,但能夠比較簡單的作個擴展支持:(同時也展示了premake的靈活性)spa

origin_libdirs = libdirs
function libdirs(dirs) 
    origin_libdirs(dirs)
    if type(dirs) == 'string' then
        dirs = { dirs }
    end
    for _, dir in ipairs(dirs) do
        linkoptions('-Wl,-rpath,' .. dir)
    end
end

將libdirs都做爲rpath編譯到binary中去。code

能夠經過readelf查看htm

readelf -d binary

而cmake則提供了比較好內建支持,有選項能夠選擇是否加入rpath。blog

 

可是,你編譯時的rpath並不表明就是你最終生產環境中的rpath,考慮一下continuous delivery中的一個狀況:

該項目有一個shared library和一個binary,在CI的build agent上編譯產生,因此指向shared library的rpath是一個指向build agent上local的path,這些artifacts會被上傳到artifact repository,而後在發佈時被部署到生產環境中,此時該rpath一定是錯誤 --- 運行失敗。

此時須要postprocess來修改rpath,有個叫作patchelf的工具:

patchelf --set-rpath /path/to/production/lib

一樣,怎麼改rpath不是重點,重點是有哪些rpath,改爲什麼樣 - 這些須要在build system在編譯過程當中收集。

還能夠去掉不須要的rpath:

patchelf --shrink-rpath program

 

3、拷貝或者symbolic link

Windows下通常直接把全部dll打包放一塊兒 - 與app同一目錄,連PATH都不用設。

Linux下咱們能夠把全部的library都symblic link到同一目錄下,PATH只要設一個便可 - 這個在網絡環境下尤爲有用,以前這篇文章也講到過。

相關文章
相關標籤/搜索