当前位置:   article > 正文

Linux笔记之LD_LIBRARY_PATH详解_ld library path

ld library path

Linux笔记之LD_LIBRARY_PATH详解

参考博文:
1.C++笔记之执行一个可执行文件时指定动态库所存放的文件夹lib的路径
2.Linux笔记之LD_LIBRARY_PATH详解
3.qt-C++笔记之使用QProcess去执行一个可执行文件时指定动态库所存放的文件夹lib的路径

code review!

1.常见使用命令来设置动态链接库路径

export LD_LIBRARY_PATH=$PWD/lib:$LD_LIBRARY_PATH 
  • 1

命令 export LD_LIBRARY_PATH=$PWD/lib:$LD_LIBRARY_PATH 在类 Unix 操作系统中用来设置环境变量 LD_LIBRARY_PATH,以便在运行时包含一个含有共享库的目录。这里是命令的详细解释:

  • export:这个 shell 内置命令用来导出环境变量,这样它就可以被 shell 启动的任何子进程使用。

  • LD_LIBRARY_PATH:这是一个环境变量,动态链接器在运行时用它来找到共享库(.so 文件)。当你运行一个依赖共享库的可执行文件时,动态链接器会使用 LD_LIBRARY_PATH 中列出的目录来定位这些库。

  • =$PWD/lib:这将 LD_LIBRARY_PATH 设置为包含当前工作目录($PWD)中的 lib 目录。PWD 环境变量包含当前工作目录的路径。

  • :$LD_LIBRARY_PATH:冒号 : 是一个分隔符,它允许你将多个目录附加到 LD_LIBRARY_PATH。这部分命令将现有的 LD_LIBRARY_PATH 内容附加到新值的前面,这样新目录就会首先被搜索,然后是之前设置的目录。

综合起来,这个命令将当前工作目录的 lib 目录添加到 LD_LIBRARY_PATH 的开头,并将这个更新后的路径导出到随后执行的程序的环境中。

这在你想要运行依赖于不在动态链接器标准查找位置(如 /lib/usr/lib)的共享库的程序时非常有用。通过设置 LD_LIBRARY_PATH,你可以引导动态链接器在额外的目录中搜索。

请注意,通常认为使用 LD_LIBRARY_PATH 是最后的手段,因为如果不能将库安装到标准位置或调整动态链接器的配置文件时才会使用,因为它可能会导致版本和兼容性问题。通常最好将其用于临时或开发目的,而不是作为库路径解析的永久解决方案。

2.LD_LIBRARY_PATH详解

LD_LIBRARY_PATH 是一个环境变量,用于在Linux和类Unix操作系统中指定动态链接器搜索共享库时应查看的目录的列表。动态链接器用于加载和链接应用程序在运行时需要的共享库(动态库,通常是.so文件)。

默认情况下,动态链接器会按照一定的规则(例如查看 /lib/usr/lib 等目录)来搜索这些共享库。但是,如果你的应用程序使用了非标准路径中的共享库,或者你想覆盖默认的库版本,你可以设置 LD_LIBRARY_PATH 来告诉动态链接器在哪些额外的目录中查找。

设置 LD_LIBRARY_PATH

你可以通过在命令行中导出环境变量来设置 LD_LIBRARY_PATH,如下所示:

export LD_LIBRARY_PATH=/path/to/mylibs:$LD_LIBRARY_PATH
  • 1

这里,/path/to/mylibs 应该替换为实际的目录路径。如果有多个目录,可以用冒号分隔它们。注意,$LD_LIBRARY_PATH 在末尾包括了原始的 LD_LIBRARY_PATH 值,这样可以在添加新路径的同时保留旧的路径。

举例

假设你有一个应用程序需要使用位于 /home/user/mylibs 目录中的共享库。你可以这样设置环境变量:

export LD_LIBRARY_PATH=/home/user/mylibs:$LD_LIBRARY_PATH
  • 1

然后运行你的应用程序。动态链接器现在会首先在 /home/user/mylibs 目录中查找共享库,如果在那里找不到,再按照默认的规则进行搜索。

注意事项

虽然 LD_LIBRARY_PATH 很方便,但过度使用或不当使用可能会导致一些问题:

  1. 安全性:如果不小心设置了错误的路径,可能会加载到错误的库,这可能会导致安全问题或应用程序崩溃。
  2. 依赖性:依赖于 LD_LIBRARY_PATH 的应用程序可能在其他环境中运行起来比较困难,因为它需要确保环境变量被正确设置。
  3. 维护性:长期依赖 LD_LIBRARY_PATH 可能会导致维护难度增加,尤其是在多用户系统或复杂的部署环境中。

为了避免这些问题,通常推荐的做法是尽可能使用标准路径来安装共享库,或者使用如 rpathrunpath 这样的链接器选项在编译时指定库的搜索路径。

3.替代方案

为了避免使用 LD_LIBRARY_PATH 可能带来的问题,可以采用以下方法确保动态链接器能够找到共享库:

使用标准路径

将共享库安装到系统的标准路径下(如 /usr/lib/lib),这样动态链接器默认就会在这些路径下查找所需的库。这通常需要管理员权限,因为涉及到修改系统目录。

编译时指定链接路径

在编译和链接应用程序时,可以使用链接器(如 ld)的选项来指定共享库的路径。这种方法在编译时将库的路径固定到二进制文件中,减少了运行时的路径搜索和环境变量的依赖。

  • rpath: 使用 -rpath 选项可以指定运行时搜索路径,链接器会将这个路径写入到二进制文件中。例如:

    gcc -o myapp myapp.c -L/path/to/mylibs -lmylib -Wl,-rpath,/path/to/mylibs
    
    • 1

    这里 -L 选项告诉编译器在哪个目录下搜索库文件,-l 选项指定库的名称,-Wl,-rpath,/path/to/mylibs 告诉链接器添加一个 rpath

  • runpath: 类似于 rpath,但是如果设置了 LD_LIBRARY_PATH 环境变量,LD_LIBRARY_PATH 会优先于 runpath。使用 runpath 的语法类似于 rpath

    gcc -o myapp myapp.c -L/path/to/mylibs -lmylib -Wl,-rpath-link,/path/to/mylibs
    
    • 1

优先使用 rpath 还是 runpath?

  • 如果你希望 LD_LIBRARY_PATH 环境变量能够覆盖编译时设置的路径,使用 runpath 是一个更好的选择。
  • 如果你希望编译时设置的路径总是被使用,即使存在 LD_LIBRARY_PATH 环境变量,那么 rpath 是更好的选择。

注意事项

  • 当使用 rpathrunpath 时,要确保指定的路径是可靠和安全的。
  • 如果共享库的位置在部署后可能会发生变化,过度依赖这些选项可能会导致以后的维护问题。
  • 一些系统可能配置有安全机制,比如 SELinux,这可能会限制应用程序只能从特定的目录加载共享库。

在决定使用 rpathrunpath 还是 LD_LIBRARY_PATH 时,需要根据应用程序的具体需求和部署环境来权衡。尽可能使用标准路径或者系统包管理器来管理共享库,这样可以最小化环境设置对应用程序正常运行的影响。

4.export LD_LIBRARY_PATH 在CMakeLists.txt中有对应的功能吗?

在 CMake 中,没有直接设置 LD_LIBRARY_PATH 环境变量的命令。不过,可以通过其他方式实现类似的功能,以确保在运行时能够正确找到动态库。

解决方案

  1. 设置 RPATH(运行时搜索路径)
    使用 RPATH(运行时库搜索路径)可以在编译时指定运行时库的搜索路径。这样在运行时,程序会使用指定的路径查找动态库,而无需设置 LD_LIBRARY_PATH

  2. 自定义命令
    通过 add_custom_commandadd_custom_target 设置环境变量。

4.1.设置 RPATH

CMake 提供了几个变量来控制 RPATH 的设置:

  • CMAKE_INSTALL_RPATH: 指定安装后的 RPATH。
  • CMAKE_BUILD_RPATH: 指定构建时的 RPATH。
  • CMAKE_INSTALL_RPATH_USE_LINK_PATH: 控制是否将链接目录添加到 RPATH。

示例:

# 指定项目名称
project(MyProject)

# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 17)

# 添加可执行文件
add_executable(myprogram "myprogram.cpp")

# 链接库
target_link_libraries(myprogram mylib)

# 设置构建时的 RPATH
set(CMAKE_BUILD_RPATH "/path/to/libs")

# 设置安装后的 RPATH
set(CMAKE_INSTALL_RPATH "/path/to/libs")

# 控制是否将链接目录添加到 RPATH
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

在这个示例中,/path/to/libs 是动态库所在的路径。这样,生成的可执行文件在运行时会使用指定的路径查找动态库。

4.2.设置 RPATH补充笔记

代码

# 设置运行时库路径(rpath)
set_target_properties(main PROPERTIES
    BUILD_RPATH "${CMAKE_SOURCE_DIR}"
    INSTALL_RPATH "${CMAKE_SOURCE_DIR}"
    INSTALL_RPATH_USE_LINK_PATH TRUE
)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

这段代码的作用是配置 main 目标的运行时库查找路径,使得在构建和安装后都能在指定目录(即源目录 ${CMAKE_SOURCE_DIR})中查找运行时库。

  • BUILD_RPATH:构建时的运行时库查找路径。
  • INSTALL_RPATH:安装后的运行时库查找路径。
  • INSTALL_RPATH_USE_LINK_PATH:将链接时的路径自动添加到 INSTALL_RPATH 中。

这种配置方式在开发中很有用,特别是当库文件位于源目录中时,可以确保可执行文件在运行时能够正确找到所需的库文件。

set_target_properties 命令用于设置目标的各种属性。在这个例子中,主要关注的是设置运行时库路径(rpath)。下面是对这段代码的详细解释。

set_target_properties

set_target_properties 命令用于设置给定目标的属性。在这个例子中,目标是 main

PROPERTIES

PROPERTIES 关键字后面跟着一系列属性及其对应的值。这里设置了三个属性:BUILD_RPATHINSTALL_RPATHINSTALL_RPATH_USE_LINK_PATH

BUILD_RPATH

BUILD_RPATH 指定了在构建时用于查找运行时库的路径。在这个例子中,BUILD_RPATH 被设置为 ${CMAKE_SOURCE_DIR},即 CMake 项目的源目录。

BUILD_RPATH "${CMAKE_SOURCE_DIR}"
  • 1

这意味着在构建 main 目标时,运行时库会在源目录下查找。

INSTALL_RPATH

INSTALL_RPATH 指定了在安装时用于查找运行时库的路径。同样地,这里也被设置为 ${CMAKE_SOURCE_DIR}

INSTALL_RPATH "${CMAKE_SOURCE_DIR}"
  • 1

这意味着在安装 main 目标后,运行时库会在源目录下查找。

INSTALL_RPATH_USE_LINK_PATH

INSTALL_RPATH_USE_LINK_PATH 是一个布尔属性。设置为 TRUE 时,它会将链接器路径自动添加到 INSTALL_RPATH 中。

INSTALL_RPATH_USE_LINK_PATH TRUE
  • 1

这意味着如果在链接时指定了某些路径,这些路径也会被添加到 INSTALL_RPATH 中。

4.3.自定义命令

如果确实需要在编译过程中设置环境变量,可以使用 add_custom_commandadd_custom_target

# 指定项目名称
project(MyProject)

# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 17)

# 添加可执行文件
add_executable(myprogram "myprogram.cpp")

# 链接库
target_link_libraries(myprogram mylib)

# 添加自定义命令来设置环境变量
add_custom_command(TARGET myprogram POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E env LD_LIBRARY_PATH="/path/to/libs" $<TARGET_FILE:myprogram>)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

这会在构建后运行可执行文件时设置 LD_LIBRARY_PATH 环境变量。

总结

  • 使用 RPATH:是最推荐的方式,因为它不依赖于环境变量,且更便于部署和管理。
  • 自定义命令:可以在构建后通过临时设置环境变量来运行程序,但这种方法不适用于所有情况。

通过以上方式,可以在 CMake 项目中实现类似于设置 LD_LIBRARY_PATH 的效果。
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/爱喝兽奶帝天荒/article/detail/826974
推荐阅读
相关标签
  

闽ICP备14008679号