-Wl参数的理解

gcc的-Wl,xxx选项将逗号分隔的标记列表作为空格分隔的参数列表传递给链接器,即:

gcc -Wl,aaa,bbb,ccc

最终变成了linker的用法:

ld aaa bbb ccc

如果是想把ld -rpath通过-Wl传递给gcc,可以是-Wl,-rpath,xxx,也可以指定-Wl的重复实例:

gcc -Wl,aaa -Wl,bbb -Wl,ccc

类似的参数

  -Wa,<options>   Pass comma-separated <options> on to the assembler
  -Wp,<options>   Pass comma-separated <options> on to the preprocessor
  -Wl,<options>   Pass comma-separated <options> on to the linker 

rpath的说明

  • 參考:https://stackoverflow.com/questions/13617137/what-is-the-difference-between-ld-library-path-and-rpath

the -rpath option encodes the path in the binary, either as DT_RPATH or DR_RUNPATH

通常,您不需要它,事实上,最好不要在可执行文件中对库搜索路径进行编码(使用-rpath选项将路径编码为二进制,可以是DT_rpath或DR_RUNPATH)

注:我自己的一般方法是在可执行文件位于构建树中,并依赖于构建树中的其他库时,将其与–rpath选项链接,以便于调试,但在安装(make install,building packages)时,需要在不使用–rpath选项的情况下重新链接,并将查找共享库的任务留给目标平台的适当动态链接器配置,例如ld.so.conf。

我的问题

在GStreamer插件注册时候发现依赖的libgstaudiosink.so找不到,而实际上系统上是有的,检查环境变量后发现和rpath配置有关。

(gst-plugin-scanner:20804): GStreamer-WARNING **: 14:35:57.201: Failed to load plugin '/usr/lib/gstreamer-1.0/libgstwestonsink.so': libgstaudiosink.so: cannot open shared object file: No such file or directory

加上-Wl到LDFLAGS后编译运行,发现就可以了。

rpath参数的写法

这里面-Wl,-rpath -Wlrpath后面是没有逗号的,这是-Wl的另外一种写法:

-Wl,-rpath -Wl,/usr/lib/gstreamer-1.0

写成下面这样是错的:

-Wl,rpath,/usr/lib/gstreamer-1.0

完整的LDFLAGS如下:

export LDFLAGS="${LDFLAGS} -lgstaudiosink -L${SYSROOT}/usr/lib/gstreamer-1.0 -L${SYSROOT}/usr/lib/gstreamer-1.0 -Wl,-rpath -Wl,/usr/lib/gstreamer-1.0"

这样libgstwestonsink加载的时候就能顺利找到libgstaudiosink.so了,所以-Wl,-rpath -Wl,/usr/lib/gstreamer-1.0指定了运行时的so搜索路径。

通过测试发现,-Wl,-rpath下面这三种写法都是可以的:

-Wl,-rpath -Wl,/usr/lib/gstreamer-1.0
-Wl,-rpath,/usr/lib/gstreamer-1.0
-Wl,-rpath=/usr/lib/gstreamer-1.0

链接选项和路径

现代连接器在处理动态库时将链接时路径(Link-time path)和运行时路径(Run-time path)分开,用户可以通过-L指定连接时库的路径,通过-R(或-rpath)指定程序运行时库的路径,大大提高了库应用的灵活性。
链接器ld的选项有 -L,-rpath 和 -rpath-link,看了下 man ld,大致是这个意思:

-L: “链接”的时候,去找的目录,也就是所有的 -l 选项里的库,都会先从 -L 指定的目录去找,然后是默认的地方。编译时的-L选项并不影响环境变量LD_LIBRARY_PATH,-L只是指定了程序编译连接时库的路径,并不影响程序执行时库的路径,系统还是会到默认路径下查找该程序所需要的库,如果找不到,还是会报错,类似cannot open shared object file。

-rpath-link:这个也是用于“链接”的时候的,例如你显示指定的需要 FOO.so,但是 FOO.so 本身是需要 BAR.so 的,后者你并没有指定,而是 FOO.so 引用到它,这个时候,会先从 -rpath-link 给的路径里找。

-rpath: “运行”的时候,去找的目录。运行的时候,要找 .so 文件,会从这个选项里指定的地方去找。对于交叉编译,交叉编译链接器需已经配置 –with-sysroot 选项才能起作用。也就是说,-rpath指定的路径会被记录在生成的可执行程序中,用于运行时查找需要加载的动态库。

参考

动态库的链接和链接选项-L,-rpath-link,-rpath

I don’t understand -Wl,-rpath -Wl,


Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐