动态库的麻烦之处在于 - 若是你的程序使用了成百上千个动态库,你的程序在运行时如何找到这些动态库? 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只要设一个便可 - 这个在网络环境下尤为有用,以前这篇文章也讲到过。