(一)
GOOGLE: gcc compile time search lib path environment;
http://xahlee.info/UnixResource_dir/_/ldpath.html 文章说:
很早以前:LD_LIBRARY_PATH 可以作为linker的搜索路径 在 -L 参数 之后被搜索!
现在:a) LD_LIBRARY_PATH不被作为linker的搜索路径, 而引入 LD_RUN_PATH 来实现linker搜索环境变量;
b) Nowadays you specify the run-time path for an executable at link stage with the 「-R」 (or sometimes 「-rpath」) flag to “ld”.
gcc 参数 -R 和 -rpath 等效。
下面贴子中的作者,估计就是用到了支持LD_LIBRARY_PATH作为linker搜索路径的版本。
http://stackoverflow.com/questions/1904990/what-is-the-difference-between-ld-library-path-and-l-at-link-time
我机器上的linker就不支持LD_LIBRARY_PATH作为linker搜索路径:
[wyh@ appimp 22:04:48]$echo $LD_LIBRARY_PATH
/home/wyh/embtv_part_2/konka_broadcom/konka_app_example/kweb_aTo_so:./
[wyh@ appimp 22:05:40]$export LD_RUN_PATH=$LD_LIBRARY_PATH
[wyh@ appimp 22:13:40]$make
mipsel-linux-g++ -L/home/wyh/embtv_part_2/konka_broadcom/usr/local/lib -lz -ldirect -ldirectfb -lfusion -Wl,-O1 -Wl,-rpath,/home/wyh/embtv_part_2/konka_broadcom/usr/local/lib -Wl,-rpath,/home/wyh/embtv_part_2/konka_broadcom/usr/qt/lib -Wl,-rpath,/usr/qt/lib -Wl,-rpath,/usr/qt/lib -o cntv_konka build/main_konka.o -L/usr/qt/lib -L. -L../bin -lbxsurf -L../cdn/bin -lbxcdn_dir -L/home/wyh/embtv_part_2/konka_broadcom/konka_app_example/main_playerDemo/mcc/ -ltplayer -L/home/wyh/embtv_part_2/konka_broadcom/konka_app_example/main/applib -lswport -L/home/wyh/embtv_part_2/konka_broadcom/usr/local/lib/ -lnexus -linit -lpthread -lQtWebKit -lQtGui -lQtNetwork -lQtCore
/home/wyh/embtv_part_2/konka_broadcom/stbgcc-4.5.3-1.3/bin/../lib/gcc/mipsel-linux-uclibc/4.5.3/../../../../mipsel-linux-uclibc/bin/ld: warning: libbxWebPlugin.so.1, needed by ../bin/libbxsurf.so, not found (try using -rpath or -rpath-link)
../bin/libbxsurf.so: undefined reference to `bxWeb_open_url'
../bin/libbxsurf.so: undefined reference to `bxWeb_create_view'
collect2: ld returned 1 exit status
make: *** [cntv_konka] Error 1
[wyh@ appimp 22:13:45]$ 后来,还参照 http://gcc.gnu.org/onlinedocs/gcc/Environment-Variables.html 官方稳当,设置了 LIBRARY_PATH环境变量,
也不管用 ---- 是在补上了 -lbxWebPlugin 来编译 cntv_konka.
==> 最后: 在exe的链接参数中:不使用 -lbxWebPlugin, 而是增加了 -Wl,-rpath,/xxx/yyy/zzz 指向存放libbxWebPlugin.so的路径, 就编译通过了!
[wyh@ appimp 23:04:08]$mipsel-linux-g++ -L/home/wyh/embtv_part_2/konka_broadcom/usr/local/lib -lz -ldirect -ldirectfb -lfusion -Wl,-O1 -Wl,-rpath,/home/wyh/embtv_part_2/konka_broadcom/usr/local/lib -Wl,-rpath,/home/wyh/embtv_part_2/konka_broadcom/usr/qt/lib -Wl,-rpath,/usr/qt/lib -Wl,-rpath,/usr/qt/lib -Wl,-rpath,/home/wyh/embtv_part_2/konka_broadcom/konka_app_example/kweb_aTo_so -o cntv_konka build/main_konka.o -L/usr/qt/lib -L. -L../bin -lbxsurf -L../cdn/bin -lbxcdn_dir -L/home/wyh/embtv_part_2/konka_broadcom/konka_app_example/main_playerDemo/mcc/ -ltplayer -L/home/wyh/embtv_part_2/konka_broadcom/konka_app_example/main/applib -lswport -L/home/wyh/embtv_part_2/konka_broadcom/usr/local/lib/ -lnexus -linit -lpthread -lQtWebKit -lQtGui -lQtNetwork -lQtCore
在 http://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_node/ld_3.html 文章中也说了: “The -rpath option is also used when locating shared objects which are needed by shared objects explicitly included in the link; see the description of the -rpath-link option.” 即-rpath同时也作为linker的搜索路径。
例如: http://www.castaglia.org/proftpd/doc/README.AIX.html 说 “Unlike other Unix systems, by default the IBM linker automatically will use the compile time library search path as the runtime shared library search path. ” IBM的linker会自动将编译时的搜索路径作为运行时的搜索路径!
修正:LIBRARY_PATH 变量是能用的,但有条件: 对于native编译才有用。 我之前测试没起作用,因为我用的是交叉编译工具链。 gcc文档就是这么说的:
“The value of LIBRARY_PATH is a colon-separated list of directories, much like PATH. When configured as a native compiler, GCC tries the directories thus specified when searching for special linker files, if it can't find them using GCC_EXEC_PREFIX. Linking using GCC also uses these directories when searching for ordinary libraries for the -l option (but directories specified with -L come first).” 注意其中的 native 字。 在优先级上, -L 指定的目录优先, 其次是 LIBRARY_PATH。
(二)-rpath 进阶
可是,现在-lbxsurf.so已经编译好了,假设不再编译新版本的话,能否用工具修改的-rpath信息呢?
==〉 可以的: 下面是 http://www.eyrie.org/~eagle/notes/rpath.html 文章中摘出来的:
Checking the binaries // 可以检查一个 so 中已经hardcoded的 rpath:
To verify that a binary is doing the right thing, use the command ldd on the binary. This will list all of the libraries and either where they came from (if found) or something like "(not found)" if the library wasn't found. On Mac OS X, use otool -L.
Solaris has the very useful -s option to ldd that will additionally show the full library search path, so you can confirm that you encoded the right rpath in the binary.
A partial equivalent under Linux is:
readelf -d <binary> | grep RPATH
but note that this only shows the rpath for a particular binary (executable or library). If a shared library depends on other shared libraries, those shared libraries may be searched for using the rpath of the shared library that is loading them. To make sure that the search path is correct on Linux, you may need to use the above readelf command on the binary and all libraries other than system libraries that it uses. readelf comes with binutils, so if you're compiling software you will probably already have it installed.
Changing the rpath //还可以修改so中的rpath信息:
On Linux, a utility called patchelf is available that can modify or remove the rpath or add one if one was not already present. This utility replaces the older chrpath utility, which appears to no longer be maintained.
patchelf won't compile on Solaris out of the box. For it, you may still need chrpath. The maintainer's FTP site used to be atftp://ftp.hungry.com/pub/hungry/chrpath/ but has been unreachable for some time. At this point, the best source is probably the Debian package.
(三) 关于链接顺序不同的结果:
http://stackoverflow.com/questions/10585225/some-questions-about-search-order-of-gcc-linker?rq=1 很好的例子!