linux指定目录搜索或链接so

当你编译一个程序,该程序依赖于某些动态链接库(如 OpenSSL)时,你需要告诉编译器和链接器在哪里找到这些库文件。使用 -L 选项指定库文件的目录,而 -Wl,-rpath-link 选项则指定在运行时程序链接这些库时,应该优先搜索的路径。这样做可以确保程序在运行时能够正确加载和链接依赖的 OpenSSL 动态链接库,避免出现类似找不到库文件的错误。

编译时使用特定目录下的so

1
export LDFLAGS="-L/opt/soft/openssl/lib -Wl,-rpath-link,/opt/soft/openssl/lib"
  1. export LDFLAGS=:
  • export 是一个 shell 命令,用于将环境变量导出,使得该变量在当前 shell 以及子进程中都可见和使用。
  • LDFLAGS 是一个环境变量,通常用来设置链接器 ld 或 ld.so 在编译和链接时使用的标志。
  1. “-L/opt/soft/openssl/lib:

-L 选项告诉链接器在指定路径 /opt/soft/openssl/lib 中搜索库文件(.so 文件)。
在这个命令中,我们指定了 OpenSSL 库文件所在的路径 /opt/soft/openssl/lib。

  1. -Wl,-rpath-link,/opt/soft/openssl/lib:
    -Wl, 是将后面的选项传递给链接器 ld 的方式。-Wl 表示将后面的选项传递给链接器。
    -rpath-link,/opt/soft/openssl/lib 是告诉链接器在运行时使用 -rpath-link 选项,并指定 /opt/soft/openssl/lib 作为动态库搜索路径。
    -rpath-link 是链接器 ld 的选项,用于指定在运行时链接动态库时搜索的路径。与 -rpath 不同的是,-rpath-link 仅影响链接时搜索路径,而不影响运行时程序的搜索路径。

  2. -Wl,-rpath,/opt/soft/openssl/lib
    -Wl,-rpath 用于在生成的可执行文件中嵌入一个运行时搜索路径。当程序运行时,动态链接器会使用这个路径查找共享库。

如果你希望程序在运行时自动查找特定路径下的共享库而不需要设置 LD_LIBRARY_PATH 环境变量,那么可以使用 -rpath。

/etc/ld.so.conf 与 LD_LIBRARY_PATH 的关系

  • 优先级: LD_LIBRARY_PATH 设置的路径优先于 /etc/ld.so.conf 中的路径。如果两者同时设置,动态链接器会优先搜索 LD_LIBRARY_PATH 指定的路径。

  • 使用场景:

    • 使用 /etc/ld.so.conf:通常用于全局配置,例如当你安装新的系统级共享库时。
    • 使用 LD_LIBRARY_PATH:用于临时性或特定程序的库文件路径设置,例如在运行某个程序时需要加载非标准位置的库文件。
  • 注意事项:

    • 修改 /etc/ld.so.conf 后需要运行 sudo ldconfig 或者 sudo ldconfig -v 来使新的配置生效。
    • LD_LIBRARY_PATH 设置的路径对当前 shell 有效,退出 shell 后会失效,除非在登录脚本中设置。
1
export LD_LIBRARY_PATH=/path/to/mylibs:$LD_LIBRARY_PATH

这会告诉系统在启动时先搜索 /path/to/mylibs 目录中的库文件,然后才是按照 /etc/ld.so.conf 中的路径顺序搜索。

程序运行时共享库(.so 文件)的搜索路径的先后顺序

  1. LD_LIBRARY_PATH 环境变量
    • 这个环境变量指定了一系列目录,在运行时动态链接器会首先在这些目录中搜索共享库。该变量可以包含多个路径,路径之间用冒号(:)分隔。
  2. 二进制文件的 rpath(旧系统)或 runpath(新系统)
    • 编译或链接时,可以使用 rpathrunpath 选项指定共享库的搜索路径,这些路径会被嵌入到可执行文件中。
    • rpath:被静态定义在二进制文件中,优先级高于 LD_LIBRARY_PATH
    • runpath:现代的替代方案,优先级低于 LD_LIBRARY_PATH,但比默认系统路径高。
    • 设置 rpathrunpath 可以通过链接时的 -Wl,-rpath,/path/to/lib-Wl,-runpath,/path/to/lib 参数。
  3. 系统默认路径
    • 通常包括 /lib/usr/lib/usr/local/lib/lib64 等目录
    • 这些路径是由系统配置的默认路径,通常是最后被搜索的。
  4. /etc/ld.so.confld.so.conf.d/ 中定义的路径
    • 系统管理员可以在/etc/ld.so.conf文件中定义额外的共享库路径。这个文件可以包含直接的路径或者指向包含更多路径的ld.so.conf.d/ 目录中的文件。
    • 这些路径会被 ldconfig 命令读取,并更新到系统的共享库缓存中。
  5. 缓存文件 /etc/ld.so.cache 中的缓存路径
    • 系统中存在一个缓存文件 /etc/ld.so.cache,它由 ldconfig 命令生成,用于加速共享库的查找。这个文件中包含了之前提到的所有路径中的共享库信息。
  6. DT_RUNPATHDT_RPATH 动态段:
    • 这些段可以在二进制文件中定义,用于指定额外的库搜索路径,DT_RUNPATH 会在 LD_LIBRARY_PATH 之后搜索,而 DT_RPATH 会在 LD_LIBRARY_PATH 之前搜索。

你可以使用 ldd <binary> 命令查看一个可执行文件加载共享库的具体路径。此外,readelf -d <binary> 可以查看 rpathrunpath 的设置。
- 这些段可以在二进制文件中定义,用于指定额外的库搜索路径,DT_RUNPATH 会在 LD_LIBRARY_PATH 之后搜索,而 DT_RPATH 会在 LD_LIBRARY_PATH 之前搜索。


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!