MongoDB驱动安装

类Unix系统动态链接时可执行与可链接格式文件中 DT_RPATH 字段的写入.

Imagem de capa

MongoDB驱动安装

unix linux gcc ld rpath runpath

背景

开发一个在线电影订票网站时考虑利用MongoDB来进行后台数据持久化。但是在编译安装MongoDB驱动时遇到一些问题。

问题

  1. WSL中传递rpath参数,得到结果是RPATH。
    > echo "int main() { return 0; }" > test.c && gcc test.c -o test -Wl,--rpath=. && readelf -d test | grep path
    0x000000000000000f (RPATH)              Library rpath: [.]
    

    当前编译器信息为:

    > gcc --version
    gcc (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609
    Copyright (C) 2015 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.  There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    

    系统信息为:

    > lsb_release -a
    No LSB modules are available.
    Distributor ID: Ubuntu
    Description:    Ubuntu 16.04.4 LTS
    Release:        16.04
    Codename:       xenial
    > cat /proc/version
    Linux version 4.4.0-17127-Microsoft (Microsoft@Microsoft.com) (gcc version 5.4.0 (GCC) ) #1-Microsoft Sun Mar 18 00:47:00 PST 2018
    
  2. 在Debian中编译,得到结果是RUNPATH。
    > echo "int main() { return 0; }" > test.c && gcc test.c -o test -Wl,--rpath=. && readelf -d test | grep path
    0x000000000000001d (RUNPATH)            Library runpath: [.]
    

    当前编译器信息为:

    > gcc --version
    gcc (Debian 6.3.0-18+deb9u1) 6.3.0 20170516
    Copyright (C) 2016 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.  There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    

    系统信息为:

    > lsb_release -a
    No LSB modules are available.
    Distributor ID: Debian
    Description:    Debian GNU/Linux 9.4 (stretch)
    Release:        9.4
    Codename:       stretch
    > cat /proc/version
    Linux version 3.16.0-5-amd64 (debian-kernel@lists.debian.org) (gcc version 4.8.4 (Debian 4.8.4-1) ) #1 SMP Debian 3.16.51-3+deb8u1 (2018-01-08)
    

结果

在Ubuntu 17.10及18.04预览版得到结果也是RUNPATH。rpath与runpath的不同,很久前的QT博客中有提到: 字段决定链接动态库时搜索的顺序。

当时搜索了许多也没有找到答案:为何较新的系统上在可执行与可链接格式文件中指定写入DT_RPATH字段对应(rpath),写入的却是DT_RUNPATH字段(对应runpath),以及怎样才能在那些系统上写入DT_RPATH字段。 查看三个系统上的相关文档,三者文档描述差不多。

> man ld
...
       -rpath=dir
           Add a directory to the runtime library search path.  This is used when linking an ELF executable with shared objects.  All -rpath arguments are concatenated and passed to the runtime linker, which uses them to locate shared
           objects at runtime.  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.  If -rpath is not used when
           linking an ELF executable, the contents of the environment variable "LD_RUN_PATH" will be used if it is defined.

           The -rpath option may also be used on SunOS.  By default, on SunOS, the linker will form a runtime search path out of all the -L options it is given.  If a -rpath option is used, the runtime search path will be formed
           exclusively using the -rpath options, ignoring the -L options.  This can be useful when using gcc, which adds many -L options which may be on NFS mounted file systems.

           For compatibility with other ELF linkers, if the -R option is followed by a directory name, rather than a file name, it is treated as the -rpath option.
...

后来终于找到了原因:Gentoo ld generates RUNPATH in library when -Wl,-rpath is used

回答是(谷歌翻译得来):

DDT_RPATH标签被弃用,DT_RUNPATH是现代的实现,有两种不同的语义。Gentoo链接编辑器(两者ld和gold)默认情况下不会生成弃用的标签。你可以(但可能不应该)通过传递来禁用这些-Wl,–disable-new-dtags,但这并不是我所说的建议。